Initial commit
This commit is contained in:
15
.claude-plugin/plugin.json
Normal file
15
.claude-plugin/plugin.json
Normal file
@@ -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"
|
||||
]
|
||||
}
|
||||
3
README.md
Normal file
3
README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# api-response-validator
|
||||
|
||||
Validate API responses against schemas and contracts
|
||||
579
commands/validate-api-responses.md
Normal file
579
commands/validate-api-responses.md
Normal file
@@ -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
|
||||
93
plugin.lock.json
Normal file
93
plugin.lock.json
Normal file
@@ -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": []
|
||||
}
|
||||
}
|
||||
6
skills/skill-adapter/assets/README.md
Normal file
6
skills/skill-adapter/assets/README.md
Normal file
@@ -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.
|
||||
32
skills/skill-adapter/assets/config-template.json
Normal file
32
skills/skill-adapter/assets/config-template.json
Normal file
@@ -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": []
|
||||
}
|
||||
}
|
||||
83
skills/skill-adapter/assets/error_codes.json
Normal file
83
skills/skill-adapter/assets/error_codes.json
Normal file
@@ -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."
|
||||
}
|
||||
]
|
||||
}
|
||||
28
skills/skill-adapter/assets/skill-schema.json
Normal file
28
skills/skill-adapter/assets/skill-schema.json
Normal file
@@ -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)"
|
||||
}
|
||||
}
|
||||
}
|
||||
27
skills/skill-adapter/assets/test-data.json
Normal file
27
skills/skill-adapter/assets/test-data.json
Normal file
@@ -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"
|
||||
}
|
||||
}
|
||||
122
skills/skill-adapter/assets/validation_report_template.html
Normal file
122
skills/skill-adapter/assets/validation_report_template.html
Normal file
@@ -0,0 +1,122 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>API Validation Report</title>
|
||||
<style>
|
||||
/* Inline CSS for styling */
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
line-height: 1.6;
|
||||
margin: 20px;
|
||||
background-color: #f8f9fa; /* Light gray background */
|
||||
color: #343a40; /* Dark gray text */
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #007bff; /* Primary color for headings */
|
||||
border-bottom: 2px solid #007bff;
|
||||
padding-bottom: 5px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: #28a745; /* Success color for subheadings */
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
color: #dc3545; /* Danger color for sub-subheadings */
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.report-section {
|
||||
margin-bottom: 20px;
|
||||
padding: 15px;
|
||||
border: 1px solid #ced4da; /* Light gray border */
|
||||
border-radius: 5px;
|
||||
background-color: #fff; /* White background */
|
||||
}
|
||||
|
||||
.validation-summary {
|
||||
margin-bottom: 20px;
|
||||
padding: 15px;
|
||||
border: 1px solid #ced4da; /* Light gray border */
|
||||
border-radius: 5px;
|
||||
background-color: #fff; /* White background */
|
||||
}
|
||||
|
||||
.validation-summary p {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.success {
|
||||
color: #28a745; /* Success color */
|
||||
}
|
||||
|
||||
.failure {
|
||||
color: #dc3545; /* Danger color */
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
th, td {
|
||||
border: 1px solid #dee2e6; /* Lighter gray border for table cells */
|
||||
padding: 8px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: #e9ecef; /* Light gray background for table headers */
|
||||
}
|
||||
|
||||
pre {
|
||||
background-color: #f0f0f0; /* Light gray background for code blocks */
|
||||
padding: 10px;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
/* Responsive design */
|
||||
@media (max-width: 768px) {
|
||||
body {
|
||||
margin: 10px;
|
||||
}
|
||||
table {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>API Validation Report</h1>
|
||||
|
||||
<div class="validation-summary">
|
||||
<p><strong>Total Requests:</strong> {{total_requests}}</p>
|
||||
<p class="success"><strong>Successful Validations:</strong> {{successful_validations}}</p>
|
||||
<p class="failure"><strong>Failed Validations:</strong> {{failed_validations}}</p>
|
||||
</div>
|
||||
|
||||
<div class="report-section">
|
||||
<h2>Validation Results</h2>
|
||||
{{validation_results}}
|
||||
</div>
|
||||
|
||||
<div class="report-section">
|
||||
<h2>Detailed Errors</h2>
|
||||
{{detailed_errors}}
|
||||
</div>
|
||||
|
||||
<div class="report-section">
|
||||
<h2>Summary</h2>
|
||||
<p>This report summarizes the API validation results. Please review the details for any failed validations.</p>
|
||||
<p>Report generated at: {{report_generation_time}}</p>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
8
skills/skill-adapter/references/README.md
Normal file
8
skills/skill-adapter/references/README.md
Normal file
@@ -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.
|
||||
69
skills/skill-adapter/references/best-practices.md
Normal file
69
skills/skill-adapter/references/best-practices.md
Normal file
@@ -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
|
||||
70
skills/skill-adapter/references/examples.md
Normal file
70
skills/skill-adapter/references/examples.md
Normal file
@@ -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
|
||||
7
skills/skill-adapter/scripts/README.md
Normal file
7
skills/skill-adapter/scripts/README.md
Normal file
@@ -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.
|
||||
42
skills/skill-adapter/scripts/helper-template.sh
Executable file
42
skills/skill-adapter/scripts/helper-template.sh
Executable file
@@ -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"
|
||||
32
skills/skill-adapter/scripts/validation.sh
Executable file
32
skills/skill-adapter/scripts/validation.sh
Executable file
@@ -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"
|
||||
Reference in New Issue
Block a user