Skip to content

Refactor meshkit/schema to wrap meshery/schemas/validation leaf package #976

@arjunmehta-git

Description

@arjunmehta-git

Context

The meshery/schemas repository now has a validation/ leaf package (github.com/meshery/schemas/validation) that owns schema-backed validation using kin-openapi. This is the Phase 0 deliverable from the validation package design document and meshery/schemas#624.

The package is a dependency-leaf: it imports kin-openapi, yaml.v3, and stdlib only. It does NOT import MeshKit or meshery/schemas/models/.... This makes it safe for meshkit/schema to import without creating cycles.

Currently, meshkit/schema owns the full validation implementation — schema loading, compilation, caching, registration, and the validation engine. The design calls for meshkit/schema to become a thin integration layer that wraps the lower-level engine from meshery/schemas/validation, rather than maintaining a separate implementation.

Current State

meshery/schemas/validation (new — leaf package)

Package: github.com/meshery/schemas/validation

Currently provides build-time schema auditing (41 rules via go run ./cmd/validate-schemas). The runtime document validation API is the next addition:

// Planned additions to the leaf package:
func ValidateDocument(data []byte) error
func ValidateWithRef(ref Ref, data []byte) error
func ValidateAny(ref Ref, value any) error
func DecodeAndValidate[T any](data []byte) (T, error)
func ValidationDetailsFromError(err error) (ValidationDetails, bool)

These will use kin-openapi's schema.VisitJSON() for constraint enforcement, with embedded schema discovery from the meshery/schemas module's filesystem.

meshkit/schema (current — full implementation)

Package: github.com/meshery/meshkit/schema

Full API surface that must be preserved or migrated:

Category Functions
Factory Default(), New(), MustNew()
Package-level Validate(), ValidateWithRef(), ValidateAs(), DetectRef()
Generic decode DecodeAndValidate[T](), DecodeAndValidateWithRef[T](), DecodeAndValidateWithValidator[T]()
Instance methods (*Validator).Validate(), .ValidateBytes(), .ValidateAny(), .Register()
Error handling ValidationDetailsFromError(), ErrValidateDocument(), etc.
Types Ref, Registration, Violation, ValidationDetails, Validator, DocumentType

Displacement Plan

Phase 1: Add runtime validation API to meshery/schemas/validation

Where: meshery/schemas repo

Add these functions to the leaf package, matching the core validation semantics that meshkit/schema currently provides:

package validation

// Ref identifies which schema to validate against.
type Ref struct {
    SchemaVersion string
    Type          DocumentType
}

// DocumentType identifies a Meshery document family.
type DocumentType string

const (
    TypeComponent    DocumentType = "component"
    TypeConnection   DocumentType = "connection"
    TypeDesign       DocumentType = "design"
    TypeEnvironment  DocumentType = "environment"
    TypeModel        DocumentType = "model"
    TypeRelationship DocumentType = "relationship"
    TypeWorkspace    DocumentType = "workspace"
)

// Violation is a field-level validation failure.
type Violation struct {
    InstancePath string
    SchemaPath   string
    Keyword      string
    Message      string
}

// ValidationDetails contains all violations for a rejected document.
type ValidationDetails struct {
    Ref            Ref
    SchemaLocation string
    Violations     []Violation
}

// ValidateDocument validates bytes against auto-detected schema.
func ValidateDocument(data []byte) error

// ValidateWithRef validates bytes against a specific schema.
func ValidateWithRef(ref Ref, data []byte) error

// ValidateAny validates a Go value against a specific schema.
func ValidateAny(ref Ref, value any) error

// ValidationDetailsFromError extracts structured details from a validation error.
func ValidationDetailsFromError(err error) (ValidationDetails, bool)

Key implementation details:

  • Schema discovery uses the embedded meshery/schemas filesystem (same approach as current meshkit/schema)
  • Schema compilation uses kin-openapi with singleflight caching (same pattern)
  • schemaVersion field detection for auto-ref (same algorithm)
  • Returns plain error with ValidationDetails extractable via errors.As

Phase 2: Refactor meshkit/schema to delegate to the leaf package

Where: meshery/meshkit repo (this issue)

Refactor meshkit/schema to:

  1. Import github.com/meshery/schemas/validation as the engine
  2. Delegate all validation calls to the leaf package
  3. Wrap leaf package errors into MeshKit ErrorV2 types
  4. Preserve the existing meshkit/schema public API for backward compatibility
package schema

import (
    schemavalidation "github.com/meshery/schemas/validation"
    "github.com/meshery/meshkit/errors"
)

// Validate delegates to the leaf package and wraps errors.
func (v *Validator) Validate(data []byte) error {
    err := v.leaf.ValidateDocument(data)
    if err != nil {
        if details, ok := schemavalidation.ValidationDetailsFromError(err); ok {
            return ErrValidateDocument(convertDetails(details))
        }
        return ErrDecodeDocument(err)
    }
    return nil
}

// ValidateAny delegates to the leaf package.
func (v *Validator) ValidateAny(ref Ref, value any) error {
    leafRef := schemavalidation.Ref{
        SchemaVersion: ref.SchemaVersion,
        Type:          schemavalidation.DocumentType(ref.Type),
    }
    return v.leaf.ValidateAny(leafRef, value)
}

What moves out of meshkit/schema:

  • Schema loading, compilation, and caching logic
  • kin-openapi import and schema visitor calls
  • Embedded schema filesystem access
  • singleflight compilation guard
  • Built-in registration discovery

What stays in meshkit/schema:

  • MeshKit-specific error wrapping (ErrorV2, error codes meshkit-11320 through meshkit-11327)
  • The public API surface (all exported functions and types)
  • MeshKit-specific integration patterns (e.g., DecodeAndValidate[T] using MeshKit encoding)

Phase 3: Bump meshery/schemas dependency in MeshKit

  • Update go.mod in meshery/meshkit to the schemas version containing the runtime validation API
  • Run go mod tidy
  • Verify all existing meshkit/schema tests pass with the delegation layer
  • Verify no API surface changes visible to consumers

Acceptance Criteria

  • meshery/schemas/validation exposes ValidateDocument, ValidateWithRef, ValidateAny, and ValidationDetailsFromError
  • meshkit/schema imports meshery/schemas/validation and delegates all validation calls
  • meshkit/schema public API surface is unchanged — no breaking changes for consumers
  • All existing meshkit/schema tests pass
  • kin-openapi is no longer a direct import in meshkit/schema (it comes transitively through the leaf package)
  • Schema compilation caching and singleflight live in the leaf package, not MeshKit
  • MeshKit error wrapping (ErrorV2 with meshkit error codes) remains in meshkit/schema
  • The dependency graph is acyclic: schemas/validation → kin-openapi; meshkit/schemaschemas/validation

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions