diff --git a/pkg/plugin/implementation/schemavalidator/README.md b/pkg/plugin/implementation/schemavalidator/README.md new file mode 100644 index 0000000..037c133 --- /dev/null +++ b/pkg/plugin/implementation/schemavalidator/README.md @@ -0,0 +1,401 @@ +# 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.