From a469bf5db59516b8e5d2ef629c839d770d2aee54 Mon Sep 17 00:00:00 2001 From: Zhongwei Li Date: Sat, 29 Nov 2025 18:52:35 +0800 Subject: [PATCH] Initial commit --- .claude-plugin/plugin.json | 15 + README.md | 3 + commands/validate-api-responses.md | 579 ++++++++++++++++++ plugin.lock.json | 93 +++ skills/skill-adapter/assets/README.md | 6 + .../skill-adapter/assets/config-template.json | 32 + skills/skill-adapter/assets/error_codes.json | 83 +++ skills/skill-adapter/assets/skill-schema.json | 28 + skills/skill-adapter/assets/test-data.json | 27 + .../assets/validation_report_template.html | 122 ++++ skills/skill-adapter/references/README.md | 8 + .../references/best-practices.md | 69 +++ skills/skill-adapter/references/examples.md | 70 +++ skills/skill-adapter/scripts/README.md | 7 + .../skill-adapter/scripts/helper-template.sh | 42 ++ skills/skill-adapter/scripts/validation.sh | 32 + 16 files changed, 1216 insertions(+) create mode 100644 .claude-plugin/plugin.json create mode 100644 README.md create mode 100644 commands/validate-api-responses.md create mode 100644 plugin.lock.json create mode 100644 skills/skill-adapter/assets/README.md create mode 100644 skills/skill-adapter/assets/config-template.json create mode 100644 skills/skill-adapter/assets/error_codes.json create mode 100644 skills/skill-adapter/assets/skill-schema.json create mode 100644 skills/skill-adapter/assets/test-data.json create mode 100644 skills/skill-adapter/assets/validation_report_template.html create mode 100644 skills/skill-adapter/references/README.md create mode 100644 skills/skill-adapter/references/best-practices.md create mode 100644 skills/skill-adapter/references/examples.md create mode 100644 skills/skill-adapter/scripts/README.md create mode 100755 skills/skill-adapter/scripts/helper-template.sh create mode 100755 skills/skill-adapter/scripts/validation.sh diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json new file mode 100644 index 0000000..3a0f734 --- /dev/null +++ b/.claude-plugin/plugin.json @@ -0,0 +1,15 @@ +{ + "name": "api-response-validator", + "description": "Validate API responses against schemas and contracts", + "version": "1.0.0", + "author": { + "name": "Jeremy Longshore", + "email": "[email protected]" + }, + "skills": [ + "./skills" + ], + "commands": [ + "./commands" + ] +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..d75f763 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# api-response-validator + +Validate API responses against schemas and contracts diff --git a/commands/validate-api-responses.md b/commands/validate-api-responses.md new file mode 100644 index 0000000..4c190ff --- /dev/null +++ b/commands/validate-api-responses.md @@ -0,0 +1,579 @@ +--- +description: Validate API responses against schemas +shortcut: validate +--- + +# Validate API Responses + +Implement comprehensive API response validation using JSON Schema, OpenAPI specifications, and custom business rules to ensure data integrity and contract compliance. + +## When to Use This Command + +Use `/validate-api-responses` when you need to: +- Ensure API responses conform to documented schemas +- Catch contract violations before they reach clients +- Validate response data types, formats, and constraints +- Implement runtime schema validation in production +- Create automated contract testing pipelines +- Monitor API compatibility across versions + +DON'T use this when: +- Building prototypes without defined schemas (premature optimization) +- Working with highly dynamic responses (consider runtime type checking instead) +- Validating simple scalar responses (overkill for basic types) + +## Design Decisions + +This command implements **JSON Schema + Ajv** as the primary approach because: +- Industry-standard schema format with wide ecosystem support +- Blazing fast validation with compiled schemas (10x faster than alternatives) +- Comprehensive format validators for dates, emails, UUIDs, etc. +- Custom keyword support for business-specific validation +- Clear, actionable error messages for debugging + +**Alternative considered: OpenAPI/Swagger validation** +- Better for full API contract validation +- Includes request validation, not just responses +- More complex setup and configuration +- Recommended when using OpenAPI for documentation + +**Alternative considered: Joi/Yup validation** +- More intuitive API for JavaScript developers +- Better TypeScript integration +- Limited to JavaScript ecosystem +- Recommended for Node.js-only projects + +## Prerequisites + +Before running this command: +1. Define response schemas (JSON Schema or OpenAPI) +2. Identify validation points (middleware, tests, runtime) +3. Determine error handling strategy +4. Plan performance impact for large payloads +5. Consider validation modes (strict vs. permissive) + +## Implementation Process + +### Step 1: Define Response Schemas +Create JSON Schema definitions for all API responses with proper constraints. + +### Step 2: Configure Validation Middleware +Set up validation middleware to intercept and validate responses automatically. + +### Step 3: Implement Custom Validators +Add business-specific validation rules beyond structural validation. + +### Step 4: Set Up Error Handling +Configure how validation errors are reported to clients and logged. + +### Step 5: Create Test Suites +Build comprehensive test suites for schema validation and edge cases. + +## Output Format + +The command generates: +- `schemas/` - JSON Schema definitions for all endpoints +- `validators/` - Compiled validator functions +- `middleware/response-validator.js` - Express/Koa middleware +- `tests/schema-validation.test.js` - Validation test suites +- `docs/api-schemas.md` - Human-readable schema documentation +- `monitoring/validation-metrics.js` - Validation failure tracking + +## Code Examples + +### Example 1: JSON Schema Validation with Ajv + +```javascript +// schemas/user-response.json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "UserResponse", + "type": "object", + "required": ["id", "email", "createdAt"], + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "email": { + "type": "string", + "format": "email", + "maxLength": 255 + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 100 + }, + "age": { + "type": "integer", + "minimum": 0, + "maximum": 150 + }, + "roles": { + "type": "array", + "items": { + "type": "string", + "enum": ["admin", "user", "moderator"] + }, + "minItems": 1, + "uniqueItems": true + }, + "preferences": { + "type": "object", + "properties": { + "theme": { + "type": "string", + "enum": ["light", "dark", "auto"] + }, + "notifications": { + "type": "boolean" + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + }, + "additionalProperties": false +} + +// validators/response-validator.js +const Ajv = require('ajv'); +const addFormats = require('ajv-formats'); +const fs = require('fs'); +const path = require('path'); + +class ResponseValidator { + constructor() { + this.ajv = new Ajv({ + allErrors: true, + removeAdditional: 'failing', + useDefaults: true, + coerceTypes: false, + strict: true + }); + + // Add format validators + addFormats(this.ajv); + + // Add custom keywords + this.addCustomKeywords(); + + // Load and compile schemas + this.schemas = this.loadSchemas(); + this.validators = {}; + } + + addCustomKeywords() { + // Custom business rule validator + this.ajv.addKeyword({ + keyword: 'businessRule', + schemaType: 'string', + compile: function(schemaValue) { + return function validate(data, dataCxt) { + switch(schemaValue) { + case 'validSubscription': + return data.subscriptionEnd > new Date().toISOString(); + case 'activeUser': + return !data.deleted && data.verified; + default: + return true; + } + }; + } + }); + } + + loadSchemas() { + const schemaDir = path.join(__dirname, '../schemas'); + const schemas = {}; + + fs.readdirSync(schemaDir).forEach(file => { + if (file.endsWith('.json')) { + const schema = JSON.parse( + fs.readFileSync(path.join(schemaDir, file), 'utf8') + ); + schemas[schema.$id] = schema; + this.ajv.addSchema(schema); + } + }); + + return schemas; + } + + getValidator(schemaId) { + if (!this.validators[schemaId]) { + const schema = this.schemas[schemaId]; + if (!schema) { + throw new Error(`Schema not found: ${schemaId}`); + } + this.validators[schemaId] = this.ajv.compile(schema); + } + return this.validators[schemaId]; + } + + validate(schemaId, data) { + const validator = this.getValidator(schemaId); + const valid = validator(data); + + if (!valid) { + return { + valid: false, + errors: this.formatErrors(validator.errors), + rawErrors: validator.errors + }; + } + + return { valid: true }; + } + + formatErrors(errors) { + return errors.map(err => ({ + field: err.instancePath || 'root', + message: err.message, + params: err.params, + keyword: err.keyword, + schemaPath: err.schemaPath + })); + } +} + +// middleware/response-validator.js +const ResponseValidator = require('../validators/response-validator'); + +function createResponseValidationMiddleware(options = {}) { + const validator = new ResponseValidator(); + const { + enabled = true, + strict = false, + logErrors = true, + includeErrorDetails = process.env.NODE_ENV !== 'production' + } = options; + + return function responseValidationMiddleware(req, res, next) { + if (!enabled) return next(); + + // Store original json method + const originalJson = res.json; + + res.json = function(data) { + // Determine schema based on route + const schemaId = determineSchema(req.route, res.statusCode); + + if (schemaId) { + const result = validator.validate(schemaId, data); + + if (!result.valid) { + if (logErrors) { + console.error('Response validation failed:', { + endpoint: req.originalUrl, + method: req.method, + schemaId, + errors: result.errors + }); + } + + if (strict) { + // In strict mode, return validation error + return originalJson.call(this, { + error: 'Response validation failed', + details: includeErrorDetails ? result.errors : undefined + }); + } + + // In non-strict mode, log but send response + // Could also send to monitoring service + } + } + + return originalJson.call(this, data); + }; + + next(); + }; +} + +function determineSchema(route, statusCode) { + // Map routes to schemas + const schemaMap = { + 'GET /users/:id': 'UserResponse', + 'GET /users': 'UserListResponse', + 'POST /users': 'UserResponse', + 'GET /products': 'ProductListResponse', + 'GET /orders/:id': 'OrderResponse' + }; + + const routeKey = `${route.method} ${route.path}`; + return schemaMap[routeKey]; +} + +module.exports = createResponseValidationMiddleware; +``` + +### Example 2: OpenAPI Response Validation + +```javascript +// validators/openapi-validator.js +const OpenAPIValidator = require('express-openapi-validator'); +const SwaggerParser = require('@apidevtools/swagger-parser'); +const fs = require('fs'); +const yaml = require('js-yaml'); + +class OpenAPIResponseValidator { + constructor(specPath) { + this.specPath = specPath; + this.spec = null; + this.middleware = null; + } + + async initialize() { + // Parse and validate OpenAPI spec + this.spec = await SwaggerParser.validate(this.specPath); + + // Create validation middleware + this.middleware = OpenAPIValidator.middleware({ + apiSpec: this.specPath, + validateRequests: false, // Only validate responses + validateResponses: { + removeAdditional: 'failing', + coerceTypes: false, + onError: (error, body, req) => { + console.error('OpenAPI validation error:', { + endpoint: req.path, + method: req.method, + error: error.message, + errors: error.errors + }); + } + }, + validateSecurity: false + }); + + return this; + } + + getMiddleware() { + return this.middleware; + } + + // Manual validation method + async validateResponse(path, method, status, response) { + const operation = this.getOperation(path, method); + if (!operation) { + throw new Error(`Operation not found: ${method} ${path}`); + } + + const responseSpec = operation.responses[status]; + if (!responseSpec) { + throw new Error(`Response not defined for status: ${status}`); + } + + const schema = responseSpec.content?.['application/json']?.schema; + if (!schema) { + return { valid: true }; // No schema defined + } + + // Validate against schema + return this.validateAgainstSchema(response, schema); + } + + getOperation(path, method) { + const pathItem = this.spec.paths[path]; + return pathItem?.[method.toLowerCase()]; + } + + validateAgainstSchema(data, schema) { + // Implementation would use Ajv or similar + // This is simplified for brevity + const Ajv = require('ajv'); + const ajv = new Ajv(); + const valid = ajv.validate(schema, data); + + return { + valid, + errors: ajv.errors + }; + } +} + +// Usage +const validator = await new OpenAPIResponseValidator('./openapi.yaml').initialize(); +app.use(validator.getMiddleware()); +``` + +### Example 3: Custom Business Rule Validation + +```javascript +// validators/business-rules.js +class BusinessRuleValidator { + constructor() { + this.rules = new Map(); + this.registerDefaultRules(); + } + + registerDefaultRules() { + // User-related rules + this.addRule('user.ageRestriction', (user) => { + if (user.role === 'admin' && user.age < 21) { + return 'Admins must be at least 21 years old'; + } + return null; + }); + + this.addRule('user.emailDomain', (user) => { + if (user.role === 'employee' && !user.email.endsWith('@company.com')) { + return 'Employees must use company email'; + } + return null; + }); + + // Order-related rules + this.addRule('order.minimumAmount', (order) => { + const total = order.items.reduce((sum, item) => + sum + (item.price * item.quantity), 0 + ); + if (total < 10) { + return 'Order must be at least $10'; + } + return null; + }); + + this.addRule('order.inventoryCheck', async (order) => { + for (const item of order.items) { + const available = await checkInventory(item.productId); + if (available < item.quantity) { + return `Insufficient inventory for product ${item.productId}`; + } + } + return null; + }); + } + + addRule(name, validator) { + this.rules.set(name, validator); + } + + async validate(context, data) { + const errors = []; + const applicableRules = Array.from(this.rules.entries()) + .filter(([name]) => name.startsWith(context)); + + for (const [name, validator] of applicableRules) { + try { + const error = await validator(data); + if (error) { + errors.push({ + rule: name, + message: error + }); + } + } catch (e) { + errors.push({ + rule: name, + message: `Rule execution failed: ${e.message}` + }); + } + } + + return { + valid: errors.length === 0, + errors + }; + } +} + +// Integration with response validation +async function validateWithBusinessRules(req, res, next) { + const originalJson = res.json; + const validator = new BusinessRuleValidator(); + + res.json = async function(data) { + const context = determineContext(req.route); + + if (context) { + const result = await validator.validate(context, data); + + if (!result.valid) { + console.error('Business rule validation failed:', result.errors); + + // Could return error or just log + if (process.env.STRICT_VALIDATION === 'true') { + return originalJson.call(this, { + error: 'Business rule validation failed', + violations: result.errors + }); + } + } + } + + return originalJson.call(this, data); + }; + + next(); +} +``` + +## Error Handling + +| Error | Cause | Solution | +|-------|-------|----------| +| "Schema not found" | Missing schema file | Ensure schema exists in schemas/ directory | +| "Invalid schema" | Malformed JSON Schema | Validate schema with JSON Schema validator | +| "Circular reference" | Schema references itself | Refactor schema to avoid circular dependencies | +| "Performance degradation" | Large payload validation | Use streaming validation or async processing | +| "Memory leak" | Schema compilation on every request | Cache compiled validators | + +## Configuration Options + +**Validation Modes** +- `strict`: Reject invalid responses (production) +- `permissive`: Log but allow invalid responses (development) +- `monitor`: Send metrics without blocking (staging) + +**Performance Tuning** +- `cacheSize`: Number of compiled schemas to cache (default: 100) +- `maxDepth`: Maximum recursion depth for nested objects (default: 10) +- `timeout`: Maximum validation time in ms (default: 1000) + +## Best Practices + +DO: +- Version your schemas alongside API versions +- Use shared schema definitions for common types +- Validate at multiple layers (client, server, database) +- Include examples in schema definitions +- Monitor validation failures in production +- Use semantic versioning for schema changes + +DON'T: +- Validate responses in production synchronously (use async) +- Include sensitive data in validation error messages +- Use overly strict validation that breaks compatibility +- Ignore validation errors in production +- Mix validation logic with business logic + +## Performance Considerations + +- Compile schemas once at startup, not per request +- Use references for shared schema components +- Consider async validation for large payloads +- Implement sampling for high-traffic endpoints +- Cache validation results for identical responses + +## Related Commands + +- `/api-contract-generator` - Generate schemas from code +- `/api-documentation-generator` - Document schemas +- `/api-testing-framework` - Test against schemas +- `/api-versioning-manager` - Handle schema evolution + +## Version History + +- v1.0.0 (2024-10): Initial implementation with JSON Schema validation +- Planned v1.1.0: GraphQL schema validation support \ No newline at end of file diff --git a/plugin.lock.json b/plugin.lock.json new file mode 100644 index 0000000..4b977a2 --- /dev/null +++ b/plugin.lock.json @@ -0,0 +1,93 @@ +{ + "$schema": "internal://schemas/plugin.lock.v1.json", + "pluginId": "gh:jeremylongshore/claude-code-plugins-plus:plugins/api-development/api-response-validator", + "normalized": { + "repo": null, + "ref": "refs/tags/v20251128.0", + "commit": "28408ec737fcc2439009417ccb68bdee68133f90", + "treeHash": "6753081541647469442e95387ad5bf232c88aae393511f0b745c2c142ce07a7b", + "generatedAt": "2025-11-28T10:18:08.174582Z", + "toolVersion": "publish_plugins.py@0.2.0" + }, + "origin": { + "remote": "git@github.com:zhongweili/42plugin-data.git", + "branch": "master", + "commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390", + "repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data" + }, + "manifest": { + "name": "api-response-validator", + "description": "Validate API responses against schemas and contracts", + "version": "1.0.0" + }, + "content": { + "files": [ + { + "path": "README.md", + "sha256": "7d6d361130ff3be58e7ac6f4cb3e35d694f81c4fd2587d286c67c827ede342bf" + }, + { + "path": ".claude-plugin/plugin.json", + "sha256": "fe034772ee2e4ea1e9496f72bc119f250a658bac5e2879d1039c1fe0849390cc" + }, + { + "path": "commands/validate-api-responses.md", + "sha256": "fd77abc65bb60b4a12a13e5ae82d904c1da0bf5c1701b15199dd11b266a343ef" + }, + { + "path": "skills/skill-adapter/references/examples.md", + "sha256": "922bbc3c4ebf38b76f515b5c1998ebde6bf902233e00e2c5a0e9176f975a7572" + }, + { + "path": "skills/skill-adapter/references/best-practices.md", + "sha256": "c8f32b3566252f50daacd346d7045a1060c718ef5cfb07c55a0f2dec5f1fb39e" + }, + { + "path": "skills/skill-adapter/references/README.md", + "sha256": "6a3efe5da6d93b9f10f74f2cd2a122ba4027d529c3753698ebf279ba20ac1eac" + }, + { + "path": "skills/skill-adapter/scripts/helper-template.sh", + "sha256": "0881d5660a8a7045550d09ae0acc15642c24b70de6f08808120f47f86ccdf077" + }, + { + "path": "skills/skill-adapter/scripts/validation.sh", + "sha256": "92551a29a7f512d2036e4f1fb46c2a3dc6bff0f7dde4a9f699533e446db48502" + }, + { + "path": "skills/skill-adapter/scripts/README.md", + "sha256": "542b455a6c39a3bc814f78da6c1e74a1e88ef31f2ee1a06524797a0ba0edec19" + }, + { + "path": "skills/skill-adapter/assets/test-data.json", + "sha256": "ac17dca3d6e253a5f39f2a2f1b388e5146043756b05d9ce7ac53a0042eee139d" + }, + { + "path": "skills/skill-adapter/assets/error_codes.json", + "sha256": "50e7790d00874912da11ddedf022db5d2722d1e7e51e19928ae521cec9eff3bd" + }, + { + "path": "skills/skill-adapter/assets/README.md", + "sha256": "19efe4ebf5ae98c24cad55420aeb55145fc1b58721fbd1136c7c49c4a68b73a6" + }, + { + "path": "skills/skill-adapter/assets/validation_report_template.html", + "sha256": "cbb8e59fd251a6102a8f68e9dfc077b776182f78df0040d025b6fd91ee39d3ec" + }, + { + "path": "skills/skill-adapter/assets/skill-schema.json", + "sha256": "f5639ba823a24c9ac4fb21444c0717b7aefde1a4993682897f5bf544f863c2cd" + }, + { + "path": "skills/skill-adapter/assets/config-template.json", + "sha256": "0c2ba33d2d3c5ccb266c0848fc43caa68a2aa6a80ff315d4b378352711f83e1c" + } + ], + "dirSha256": "6753081541647469442e95387ad5bf232c88aae393511f0b745c2c142ce07a7b" + }, + "security": { + "scannedAt": null, + "scannerVersion": null, + "flags": [] + } +} \ No newline at end of file diff --git a/skills/skill-adapter/assets/README.md b/skills/skill-adapter/assets/README.md new file mode 100644 index 0000000..1efeef2 --- /dev/null +++ b/skills/skill-adapter/assets/README.md @@ -0,0 +1,6 @@ +# Assets + +Bundled resources for api-response-validator skill + +- [ ] validation_report_template.html: HTML template for generating validation reports. +- [ ] error_codes.json: JSON file containing error codes and descriptions. diff --git a/skills/skill-adapter/assets/config-template.json b/skills/skill-adapter/assets/config-template.json new file mode 100644 index 0000000..16f1712 --- /dev/null +++ b/skills/skill-adapter/assets/config-template.json @@ -0,0 +1,32 @@ +{ + "skill": { + "name": "skill-name", + "version": "1.0.0", + "enabled": true, + "settings": { + "verbose": false, + "autoActivate": true, + "toolRestrictions": true + } + }, + "triggers": { + "keywords": [ + "example-trigger-1", + "example-trigger-2" + ], + "patterns": [] + }, + "tools": { + "allowed": [ + "Read", + "Grep", + "Bash" + ], + "restricted": [] + }, + "metadata": { + "author": "Plugin Author", + "category": "general", + "tags": [] + } +} diff --git a/skills/skill-adapter/assets/error_codes.json b/skills/skill-adapter/assets/error_codes.json new file mode 100644 index 0000000..d6b972d --- /dev/null +++ b/skills/skill-adapter/assets/error_codes.json @@ -0,0 +1,83 @@ +{ + "_comment": "Error codes and descriptions for the API Response Validator plugin.", + "error_codes": [ + { + "code": "SCHEMA_VALIDATION_FAILED", + "description": "The API response failed validation against the provided JSON Schema.", + "details": { + "_comment": "Example details structure. 'errors' will contain schema validation errors.", + "errors": [ + { + "dataPath": ".data.id", + "schemaPath": "#/properties/id/type", + "keyword": "type", + "message": "should be string" + } + ] + }, + "severity": "ERROR", + "resolution": "Review the API response and the JSON Schema to identify and correct any discrepancies. Ensure data types and required fields match the schema definition." + }, + { + "code": "OPENAPI_VALIDATION_FAILED", + "description": "The API response failed validation against the OpenAPI specification.", + "details": { + "_comment": "Example details structure. 'errors' will contain OpenAPI validation errors.", + "errors": [ + { + "message": "Response body does not conform to schema for 200 response." + } + ], + "operationId": "getUserById", + "path": "/users/{userId}", + "method": "GET" + }, + "severity": "ERROR", + "resolution": "Review the API response and the OpenAPI specification to identify and correct any discrepancies. Check for missing or incorrect data types, required fields, and response codes." + }, + { + "code": "CONTRACT_VALIDATION_FAILED", + "description": "The API response failed validation against the custom contract rules.", + "details": { + "_comment": "Example details structure. 'failed_rules' contains information about the failed custom rules.", + "failed_rules": [ + { + "rule_name": "response_time_limit", + "message": "Response time exceeded the allowed limit of 500ms. Actual time: 750ms", + "actual_value": 750, + "expected_value": 500 + } + ] + }, + "severity": "WARNING", + "resolution": "Review the API response and the custom contract rules to identify and correct any discrepancies. Adjust the rules or the API implementation as needed." + }, + { + "code": "MISSING_CONTENT_TYPE", + "description": "The API response is missing the 'Content-Type' header.", + "details": null, + "severity": "WARNING", + "resolution": "Ensure the API response includes the 'Content-Type' header to properly identify the response format." + }, + { + "code": "INVALID_JSON", + "description": "The API response body is not valid JSON.", + "details": { + "_comment": "Details might include the parsing error message.", + "error_message": "Unexpected token '}' at position 10." + }, + "severity": "ERROR", + "resolution": "Ensure the API response returns a valid JSON payload. Check for syntax errors and proper formatting." + }, + { + "code": "UNEXPECTED_STATUS_CODE", + "description": "The API returned an unexpected HTTP status code.", + "details": { + "expected_status_code": 200, + "actual_status_code": 500 + }, + "severity": "WARNING", + "resolution": "Verify the expected HTTP status code against the actual status code returned by the API. Investigate the API logs for potential errors." + } + ] +} \ No newline at end of file diff --git a/skills/skill-adapter/assets/skill-schema.json b/skills/skill-adapter/assets/skill-schema.json new file mode 100644 index 0000000..8dc154c --- /dev/null +++ b/skills/skill-adapter/assets/skill-schema.json @@ -0,0 +1,28 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Claude Skill Configuration", + "type": "object", + "required": ["name", "description"], + "properties": { + "name": { + "type": "string", + "pattern": "^[a-z0-9-]+$", + "maxLength": 64, + "description": "Skill identifier (lowercase, hyphens only)" + }, + "description": { + "type": "string", + "maxLength": 1024, + "description": "What the skill does and when to use it" + }, + "allowed-tools": { + "type": "string", + "description": "Comma-separated list of allowed tools" + }, + "version": { + "type": "string", + "pattern": "^\\d+\\.\\d+\\.\\d+$", + "description": "Semantic version (x.y.z)" + } + } +} diff --git a/skills/skill-adapter/assets/test-data.json b/skills/skill-adapter/assets/test-data.json new file mode 100644 index 0000000..f0cd871 --- /dev/null +++ b/skills/skill-adapter/assets/test-data.json @@ -0,0 +1,27 @@ +{ + "testCases": [ + { + "name": "Basic activation test", + "input": "trigger phrase example", + "expected": { + "activated": true, + "toolsUsed": ["Read", "Grep"], + "success": true + } + }, + { + "name": "Complex workflow test", + "input": "multi-step trigger example", + "expected": { + "activated": true, + "steps": 3, + "toolsUsed": ["Read", "Write", "Bash"], + "success": true + } + } + ], + "fixtures": { + "sampleInput": "example data", + "expectedOutput": "processed result" + } +} diff --git a/skills/skill-adapter/assets/validation_report_template.html b/skills/skill-adapter/assets/validation_report_template.html new file mode 100644 index 0000000..a32b07c --- /dev/null +++ b/skills/skill-adapter/assets/validation_report_template.html @@ -0,0 +1,122 @@ + + + + + + API Validation Report + + + + +

API Validation Report

+ +
+

Total Requests: {{total_requests}}

+

Successful Validations: {{successful_validations}}

+

Failed Validations: {{failed_validations}}

+
+ +
+

Validation Results

+ {{validation_results}} +
+ +
+

Detailed Errors

+ {{detailed_errors}} +
+ +
+

Summary

+

This report summarizes the API validation results. Please review the details for any failed validations.

+

Report generated at: {{report_generation_time}}

+
+ + + \ No newline at end of file diff --git a/skills/skill-adapter/references/README.md b/skills/skill-adapter/references/README.md new file mode 100644 index 0000000..ed78f2e --- /dev/null +++ b/skills/skill-adapter/references/README.md @@ -0,0 +1,8 @@ +# References + +Bundled resources for api-response-validator skill + +- [ ] json_schema_example.json: Example JSON schema for API response validation. +- [ ] openapi_example.yaml: Example OpenAPI specification for API response validation. +- [ ] custom_rules_example.yaml: Example custom rules configuration file. +- [ ] api_response_validation_best_practices.md: Best practices for API response validation. diff --git a/skills/skill-adapter/references/best-practices.md b/skills/skill-adapter/references/best-practices.md new file mode 100644 index 0000000..3505048 --- /dev/null +++ b/skills/skill-adapter/references/best-practices.md @@ -0,0 +1,69 @@ +# Skill Best Practices + +Guidelines for optimal skill usage and development. + +## For Users + +### Activation Best Practices + +1. **Use Clear Trigger Phrases** + - Match phrases from skill description + - Be specific about intent + - Provide necessary context + +2. **Provide Sufficient Context** + - Include relevant file paths + - Specify scope of analysis + - Mention any constraints + +3. **Understand Tool Permissions** + - Check allowed-tools in frontmatter + - Know what the skill can/cannot do + - Request appropriate actions + +### Workflow Optimization + +- Start with simple requests +- Build up to complex workflows +- Verify each step before proceeding +- Use skill consistently for related tasks + +## For Developers + +### Skill Development Guidelines + +1. **Clear Descriptions** + - Include explicit trigger phrases + - Document all capabilities + - Specify limitations + +2. **Proper Tool Permissions** + - Use minimal necessary tools + - Document security implications + - Test with restricted tools + +3. **Comprehensive Documentation** + - Provide usage examples + - Document common pitfalls + - Include troubleshooting guide + +### Maintenance + +- Keep version updated +- Test after tool updates +- Monitor user feedback +- Iterate on descriptions + +## Performance Tips + +- Scope skills to specific domains +- Avoid overlapping trigger phrases +- Keep descriptions under 1024 chars +- Test activation reliability + +## Security Considerations + +- Never include secrets in skill files +- Validate all inputs +- Use read-only tools when possible +- Document security requirements diff --git a/skills/skill-adapter/references/examples.md b/skills/skill-adapter/references/examples.md new file mode 100644 index 0000000..b1d8bd2 --- /dev/null +++ b/skills/skill-adapter/references/examples.md @@ -0,0 +1,70 @@ +# Skill Usage Examples + +This document provides practical examples of how to use this skill effectively. + +## Basic Usage + +### Example 1: Simple Activation + +**User Request:** +``` +[Describe trigger phrase here] +``` + +**Skill Response:** +1. Analyzes the request +2. Performs the required action +3. Returns results + +### Example 2: Complex Workflow + +**User Request:** +``` +[Describe complex scenario] +``` + +**Workflow:** +1. Step 1: Initial analysis +2. Step 2: Data processing +3. Step 3: Result generation +4. Step 4: Validation + +## Advanced Patterns + +### Pattern 1: Chaining Operations + +Combine this skill with other tools: +``` +Step 1: Use this skill for [purpose] +Step 2: Chain with [other tool] +Step 3: Finalize with [action] +``` + +### Pattern 2: Error Handling + +If issues occur: +- Check trigger phrase matches +- Verify context is available +- Review allowed-tools permissions + +## Tips & Best Practices + +- ✅ Be specific with trigger phrases +- ✅ Provide necessary context +- ✅ Check tool permissions match needs +- ❌ Avoid vague requests +- ❌ Don't mix unrelated tasks + +## Common Issues + +**Issue:** Skill doesn't activate +**Solution:** Use exact trigger phrases from description + +**Issue:** Unexpected results +**Solution:** Check input format and context + +## See Also + +- Main SKILL.md for full documentation +- scripts/ for automation helpers +- assets/ for configuration examples diff --git a/skills/skill-adapter/scripts/README.md b/skills/skill-adapter/scripts/README.md new file mode 100644 index 0000000..9ed6431 --- /dev/null +++ b/skills/skill-adapter/scripts/README.md @@ -0,0 +1,7 @@ +# Scripts + +Bundled resources for api-response-validator skill + +- [ ] validate_json_schema.py: Script to validate API responses against a JSON schema. +- [ ] validate_openapi.py: Script to validate API responses against an OpenAPI specification. +- [ ] validate_custom_rules.py: Script to validate API responses against custom rules defined in a configuration file. diff --git a/skills/skill-adapter/scripts/helper-template.sh b/skills/skill-adapter/scripts/helper-template.sh new file mode 100755 index 0000000..c4aae90 --- /dev/null +++ b/skills/skill-adapter/scripts/helper-template.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# Helper script template for skill automation +# Customize this for your skill's specific needs + +set -e + +function show_usage() { + echo "Usage: $0 [options]" + echo "" + echo "Options:" + echo " -h, --help Show this help message" + echo " -v, --verbose Enable verbose output" + echo "" +} + +# Parse arguments +VERBOSE=false + +while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + show_usage + exit 0 + ;; + -v|--verbose) + VERBOSE=true + shift + ;; + *) + echo "Unknown option: $1" + show_usage + exit 1 + ;; + esac +done + +# Your skill logic here +if [ "$VERBOSE" = true ]; then + echo "Running skill automation..." +fi + +echo "✅ Complete" diff --git a/skills/skill-adapter/scripts/validation.sh b/skills/skill-adapter/scripts/validation.sh new file mode 100755 index 0000000..590af58 --- /dev/null +++ b/skills/skill-adapter/scripts/validation.sh @@ -0,0 +1,32 @@ +#!/bin/bash +# Skill validation helper +# Validates skill activation and functionality + +set -e + +echo "🔍 Validating skill..." + +# Check if SKILL.md exists +if [ ! -f "../SKILL.md" ]; then + echo "❌ Error: SKILL.md not found" + exit 1 +fi + +# Validate frontmatter +if ! grep -q "^---$" "../SKILL.md"; then + echo "❌ Error: No frontmatter found" + exit 1 +fi + +# Check required fields +if ! grep -q "^name:" "../SKILL.md"; then + echo "❌ Error: Missing 'name' field" + exit 1 +fi + +if ! grep -q "^description:" "../SKILL.md"; then + echo "❌ Error: Missing 'description' field" + exit 1 +fi + +echo "✅ Skill validation passed"