Skip to content

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

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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions