Framework.SchemaRegistry (Framework v0.5.0)

View Source

Schema registry + digesting + append-time size/PII enforcement.

Implementation per wire-contracts-ci-gates.md:

  • JSON Schema is single source of truth
  • Schema registry with $id, x_schema_version, x_schema_digest, x_max_bytes, x_pii_tags
  • Append-time enforcement BEFORE ExJsonSchema validation
  • Transaction rollback on violations
  • Boot loader reads schemas into ETS with digest verification

Enforcement order (binding):

  1. Check x_max_bytes size limit
  2. Check x_pii_tags violations
  3. Then validate JSON with ExJsonSchema
  4. Record schema markers for replay verification

Summary

Functions

Compute SHA256 digest of schema content.

Get schema information by schema_id.

Register a schema in the registry with full validation.

Validate payload against schema with append-time enforcement.

Verify schema digest matches current registry. Used during replay to detect schema drift.

Types

t()

@type t() :: %Framework.SchemaRegistry{
  json_schema: map(),
  max_bytes: integer(),
  pii_tags: [String.t()],
  schema_digest: String.t(),
  schema_id: String.t(),
  schema_version: integer()
}

validation_error()

@type validation_error() ::
  {:size_limit_exceeded, integer(), integer()}
  | {:pii_violation, [String.t()]}
  | {:schema_validation_failed, any()}
  | {:schema_not_found, String.t()}

Functions

child_spec(opts)

compute_schema_digest(schema)

@spec compute_schema_digest(map()) :: String.t()

Compute SHA256 digest of schema content.

Digest is computed over the canonical JSON representation excluding the x_schema_digest field itself to avoid circular dependency.

get_schema(schema_id)

@spec get_schema(String.t()) :: {:ok, t()} | {:error, :not_found}

Get schema information by schema_id.

init(args)

register_schema(schema)

@spec register_schema(map()) :: :ok | {:error, String.t()}

Register a schema in the registry with full validation.

Schema must include:

  • $id: Unique schema identifier
  • x_schema_id: Same as $id for consistency
  • x_schema_version: Integer version
  • x_schema_digest: SHA256 digest of schema content
  • x_max_bytes: Size limit (default 64 KiB, max 256 KiB)
  • x_pii_tags: List of fields containing PII

start_link(opts \\ [])

validate_payload(schema_id, payload)

@spec validate_payload(String.t(), map()) ::
  {:ok,
   %{
     schema_id: String.t(),
     schema_version: integer(),
     schema_digest: String.t()
   }}
  | {:error, validation_error()}

Validate payload against schema with append-time enforcement.

Enforcement order per wire-contracts-ci-gates.md:

  1. Check x_max_bytes size limit
  2. Check x_pii_tags violations
  3. Validate JSON with ExJsonSchema

Returns {:ok, schema_markers} or {:error, validation_error()}

verify_digest(schema_id, expected_digest)

@spec verify_digest(String.t(), String.t()) :: :ok | {:error, :digest_mismatch}

Verify schema digest matches current registry. Used during replay to detect schema drift.