# SchemaValidator Plugin A JSON schema validation plugin for beckn-onix that validates incoming request payloads against pre-defined JSON schemas based on domain, version, and endpoint. ## Overview The SchemaValidator plugin provides robust JSON schema validation for beckn-onix requests. It automatically loads and caches JSON schemas from a directory structure and validates incoming payloads based on the context information (domain and version) and the API endpoint. ## Features - **Automatic Schema Loading**: Recursively loads all JSON schema files from a specified directory - **Context-Aware Validation**: Validates payloads based on domain, version, and endpoint extracted from the request - **Schema Caching**: Caches compiled schemas in memory for fast validation - **Detailed Error Reporting**: Provides specific validation errors with field paths and messages - **Flexible Directory Structure**: Supports nested directory structures for organizing schemas - **Domain Normalization**: Handles domain names with colons (e.g., converts `nic2004:52110` to `nic2004_52110`) ## Configuration ### Plugin Configuration In your beckn-onix configuration file: ```yaml plugins: schemaValidator: id: schemavalidator config: schemaDir: ./schemas # Path to directory containing JSON schema files ``` ### Configuration Options | Field | Type | Required | Description | |-------|------|----------|-------------| | `schemaDir` | string | Yes | Path to the directory containing JSON schema files | ## Schema Directory Structure The plugin expects a specific directory structure for organizing schemas: ``` schemas/ ├── domain1/ │ ├── v1.0/ │ │ ├── search.json │ │ ├── select.json │ │ └── init.json │ └── v2.0/ │ ├── search.json │ └── select.json ├── nic2004_52110/ │ └── v1.0/ │ ├── search.json │ └── on_search.json └── mobility/ └── v1.0/ ├── search.json ├── init.json └── confirm.json ``` ### Schema File Naming Convention Schemas are organized in a three-level hierarchy: 1. **Domain**: The domain from the request context (e.g., `retail`, `mobility`, `nic2004_52110`) 2. **Version**: The version prefixed with 'v' (e.g., `v1.0`, `v2.0`) 3. **Endpoint**: The API endpoint name (e.g., `search.json`, `on_search.json`) ### Schema Key Generation The plugin generates cache keys using the format: `{domain}_{version}_{endpoint}` For example: - Domain: `nic2004:52110` → normalized to `nic2004_52110` - Version: `1.0` → prefixed to `v1.0` - Endpoint: `search` - **Final cache key**: `nic2004_52110_v1.0_search` ## Schema Validation Process ### 1. Request Analysis The plugin extracts validation parameters from: - **Request payload**: `context.domain` and `context.version` - **Request URL**: endpoint name from the URL path ### 2. Schema Selection Based on the extracted information, it: 1. Normalizes the domain name (replaces `:` with `_`) 2. Prefixes version with `v` 3. Constructs the schema key: `{domain}_{version}_{endpoint}` 4. Retrieves the corresponding schema from cache ### 3. Validation Validates the entire request payload against the selected schema using the [jsonschema/v6](https://github.com/santhosh-tekuri/jsonschema) library. ## Example Schema Files ### Basic Schema Structure All schemas should validate the context object: ```json { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "context": { "type": "object", "properties": { "domain": { "type": "string" }, "version": { "type": "string" }, "action": { "type": "string" }, "bap_id": { "type": "string" }, "bpp_id": { "type": "string" }, "transaction_id": { "type": "string", "format": "uuid" }, "message_id": { "type": "string", "format": "uuid" }, "timestamp": { "type": "string", "format": "date-time" } }, "required": ["domain", "version", "action"] } }, "required": ["context"] } ``` ### Search Endpoint Schema Example `schemas/retail/v1.0/search.json`: ```json { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "context": { "type": "object", "properties": { "domain": {"type": "string"}, "version": {"type": "string"}, "action": {"const": "search"} }, "required": ["domain", "version", "action"] }, "message": { "type": "object", "properties": { "intent": { "type": "object", "properties": { "item": { "type": "object", "properties": { "descriptor": { "type": "object", "properties": { "name": {"type": "string"} } } } } } } } } }, "required": ["context", "message"] } ``` ## Request Payload Format The plugin expects incoming requests to have this structure: ```json { "context": { "domain": "retail", "version": "1.0", "action": "search", "bap_id": "example-bap", "bpp_id": "example-bpp", "transaction_id": "uuid-here", "message_id": "uuid-here", "timestamp": "2023-06-15T09:30:00.000Z" }, "message": { // endpoint-specific payload } } ``` ## Error Handling The plugin provides detailed error reporting for validation failures: ### Schema Validation Errors When validation fails, the plugin returns a `SchemaValidationErr` with detailed information: ```json { "type": "SCHEMA_VALIDATION_ERROR", "errors": [ { "path": "context.action", "message": "missing property 'action'" }, { "path": "message.intent.item", "message": "property 'item' is required" } ] } ``` ### Common Error Types - **Missing Context Fields**: `missing field Domain in context` or `missing field Version in context` - **Schema Not Found**: `schema not found for domain: {domain}` - **JSON Parse Error**: `failed to parse JSON payload` - **Validation Failure**: Detailed field-level validation errors ## Usage Examples ### 1. Valid Request **Request URL**: `POST /search` **Payload**: ```json { "context": { "domain": "retail", "version": "1.0", "action": "search" }, "message": { "intent": { "item": { "descriptor": { "name": "laptop" } } } } } ``` **Schema Used**: `schemas/retail/v1.0/search.json` **Result**: ✅ Validation passes ### 2. Domain with Special Characters **Request URL**: `POST /search` **Payload**: ```json { "context": { "domain": "nic2004:52110", "version": "1.0", "action": "search" }, "message": {} } ``` **Schema Used**: `schemas/nic2004_52110/v1.0/search.json` **Result**: ✅ Domain normalized automatically ### 3. Missing Required Field **Request URL**: `POST /search` **Payload**: ```json { "context": { "domain": "retail", "version": "1.0" // missing "action" field }, "message": {} } ``` **Result**: ❌ Validation fails with detailed error ## Setup Instructions ### 1. Directory Setup Create your schema directory structure: ```bash mkdir -p schemas/retail/v1.0 mkdir -p schemas/mobility/v1.0 mkdir -p schemas/nic2004_52110/v1.0 ``` ### 2. Add Schema Files Create JSON schema files for each endpoint in the appropriate directories. ### 3. Configure Plugin Add the schemavalidator plugin to your beckn-onix configuration: ```yaml plugins: schemaValidator: id: schemavalidator config: schemaDir: ./schemas ``` ### 4. Start beckn-onix The plugin will automatically: - Load all schema files during initialization - Cache compiled schemas for fast validation - Validate incoming requests against appropriate schemas ## Best Practices ### Schema Design 1. **Always validate context**: Ensure all schemas validate the required context fields 2. **Use specific constraints**: Use `const` for exact matches (e.g., action names) 3. **Define required fields**: Clearly specify which fields are mandatory 4. **Use format validation**: Leverage built-in formats like `uuid`, `date-time`, `email` ### Directory Organization 1. **Consistent naming**: Use lowercase, underscore-separated names for domains 2. **Version management**: Keep different versions in separate directories 3. **Clear endpoint names**: Use descriptive names that match your API endpoints ### Error Handling 1. **Specific schemas**: Create endpoint-specific schemas for better validation 2. **Meaningful error messages**: Design schemas to provide clear validation feedback 3. **Test schemas**: Validate your schemas against sample payloads ## Testing Run the plugin tests: ```bash cd pkg/plugin/implementation/schemavalidator go test -v ./... ``` ## Performance Considerations - **Schema Caching**: Schemas are compiled once during initialization and cached in memory - **Fast Validation**: Uses efficient jsonschema library for validation - **Memory Usage**: Schemas are kept in memory for the lifetime of the application ## Troubleshooting ### Common Issues 1. **Schema not found** - Verify directory structure matches `domain/version/endpoint.json` - Check domain normalization (`:` becomes `_`) - Ensure version is prefixed with `v` 2. **Schema compilation failed** - Validate JSON schema syntax - Check for circular references - Ensure schema follows JSON Schema Draft 7 3. **Validation fails unexpectedly** - Compare request payload with schema requirements - Check for typos in field names - Verify data types match schema expectations ### Debug Mode Enable debug logging to see detailed validation information: ```yaml log: level: debug ``` This will show: - Schema loading process - Cache key generation - Validation attempts - Error details ## Dependencies - [jsonschema/v6](https://github.com/santhosh-tekuri/jsonschema): JSON Schema validation library - Standard Go libraries for file system operations ## License This plugin follows the same license as the main beckn-onix project.