ENSEMBLU SchemaGuard Β· axiom-language 3.0.0
Project Axiom Β· Perimeter Validation

SchemaGuard

You give it data and a schema. It returns a clear Result β€” valid data, or a plain-English reason why not. Never a crash.

Every payload crossing your boundary β€” API body, config file, upload β€” either matches the shape you expect, or it doesn’t.

SchemaGuard answers that in one handshake:

βœ“ Valid
Result.success β€” data is safe to use as-is.
βœ— Invalid
Result.failure β€” what failed, and where.

No exceptions thrown for β€œbad shape.” No half-processed data leaking through.

What it replaces

The usual way
  • Annotate a class; hope the framework wires it
  • Reflection scans objects at runtime
  • Bad data throws deep in unrelated code
  • Debug by chasing a stack trace
With SchemaGuard
  • Write the schema once as a plain .axiom file
  • No annotations, no reflection, no scanning
  • Bad data never throws β€” you get a Result
  • The failure message names the field and rule

How you actually use it (3.0.0)

Content is a MemorySegment (heap, native or memory-mapped) or an already-parsed map. Three steps. That’s the whole interaction.

Primary path β€” MemorySegment + built-in AxiomDopParser
final var content = MemorySegment.ofArray(contentBytes); // or FileChannel.map(..)
final var result = SchemaGuard
        .checkContent(content)
        .basedOnSchemaInPath("user-profile")
        .withAxiomParser();
JSON body (e.g. HTTP request) β€” plug in JsonParser
final var data = SchemaGuard
        .checkContent(body)   // body = MemorySegment.ofArray(request bytes)
        .basedOnSchemaInPath("schemas/account_query_schema")
        .withParser(seg -> JsonParser.take(seg)
                .openBuffer()
                .ensureRootIsObject()
                .parseObject())
        .getOrThrow();
Already-parsed map β€” skip re-parse
final var result = SchemaGuard
        .checkContent(myPersistentMap)
        .basedOnSchemaInPath("user-profile")
        .withAxiomParser();
1

Hand it a MemorySegment or a PersistentMap.

2

Name the schema file via basedOnSchemaInPath.

3

Get a Result β€” never a structural crash.

⚠️ Breaking Changes in 3.0.0
  • checkContent(byte[]) is now checkContent(MemorySegment). Wrap existing arrays with MemorySegment.ofArray(bytes). checkContent(PersistentMap) is unchanged.
  • withParser is now Function<MemorySegment, PersistentMap<String, Object>>.
  • Schemas are memory-mapped into a shared arena and cached. Use SchemaGuard.reload(path) / reloadAll() for hot reload.
  • Full details: 2.0.0 β†’ 3.0.0 changelog.

Writing a schema: the .axiom file

A schema is a plain file, not code. Drop it under schemas/, reference it by path β€” nothing to compile or annotate.

schemas/account_query_schema.axiom
{
  required: [status, limit]
  properties: {
    status: {
      type: string
      enum: [ACTIVE, INACTIVE, SUSPENDED, PENDING]
    }
    limit: {
      type: integer
      min: 1
      max: 1000
      description: Maximum records per fetch.
    }
  }
}

Part of axiom-language Β· depends on axiom-sovereign + axiom