Prismatic Plugin Development Kit
Build Custom Intelligence Sources
The Prismatic Plugin Development Kit provides a comprehensive framework for creating custom intelligence adapters, threat feeds, and analysis pipelines. With built-in scaffolding, testing frameworks, and deployment tools, you can extend the platform's capabilities to meet your specific intelligence requirements.
Why Build Plugins?
- 🎯 Specialized Sources: Access proprietary or niche intelligence feeds
- 🔧 Custom Logic: Implement domain-specific analysis algorithms
- 🚀 Rapid Development: Scaffold-to-production in under an hour
- 🧪 Battle-Tested Framework: Production-proven patterns and best practices
- 🌐 Community Ecosystem: Share and discover plugins with thousands of developers
Plugin Architecture
Core Components
// Plugin interface structure
interface PrismaticPlugin {
// Plugin metadata
metadata: PluginMetadata;
// Data source configuration
source: SourceConfiguration;
// Query processing
execute(query: QueryInput): Promise<QueryResult>;
// Health checking
healthCheck(): Promise<HealthStatus>;
// Rate limiting
getRateLimit(): RateLimitInfo;
}Plugin Types
1. OSINT Adapters
- Domain intelligence sources
- Social media APIs
- Public record databases
- Certificate transparency logs
2. Threat Intelligence Feeds
- IOC (Indicators of Compromise) sources
- Malware analysis APIs
- Vulnerability databases
- Dark web monitoring
3. Analysis Pipelines
- Custom scoring algorithms
- Data correlation engines
- Risk assessment models
- Behavioral analysis
4. Data Transformers
- Format converters
- Data enrichment
- Normalization pipelines
- Aggregation functions
Quick Start
Installation
# Install the plugin development kit
npm install -g @prismatic-platform/plugin-kit
# Create new plugin project
prismatic-plugin init my-custom-source --type=osint-adapter
cd my-custom-source
npm installProject Structure
my-custom-source/
├── src/
│ ├── index.ts # Main plugin entry point
│ ├── adapter.ts # Core adapter logic
│ ├── types.ts # TypeScript definitions
│ └── utils.ts # Helper functions
├── tests/
│ ├── adapter.test.ts # Unit tests
│ ├── integration.test.ts # Integration tests
│ └── fixtures/ # Test data
├── docs/
│ ├── README.md # Plugin documentation
│ └── API.md # API reference
├── config/
│ ├── schema.json # Configuration schema
│ └── examples/ # Example configurations
├── package.json # Dependencies and scripts
├── prismatic.config.js # Plugin configuration
└── docker/
└── Dockerfile # Container definition
Building Your First Plugin
1. Define Plugin Metadata
// src/index.ts
import { createPlugin } from '@prismatic-platform/plugin-kit';
export const customThreatFeed = createPlugin({
// Plugin identification
: 'custom-threat-feed',
: '1.0.0',
: 'Custom threat intelligence aggregator',
: 'Your Name <your.email@example.com>',
// Plugin capabilities
: {
: ['domain', 'ip', 'hash'],
: true,
: false,
: true
},
// Configuration schema
: {
: 'object',
: {
: {
: 'string',
: 'API key for threat feed service'
},
: {
: 'string',
: 'uri',
: 'API endpoint URL'
},
: {
: 'number',
: 30000,
: 'Request timeout in milliseconds'
}
},
: ['apiKey', 'endpoint']
}
});2. Implement Core Logic
// src/adapter.ts
import { PluginAdapter, QueryInput, QueryResult } from '@prismatic-platform/plugin-kit';
export class CustomThreatFeedAdapter extends PluginAdapter {
async execute(query: QueryInput): Promise<QueryResult> {
const { indicator, type } = query;
try {
// Call external API
const response = await this.httpClient.get`/indicators/${type}/${indicator}`, {
: {
'Authorization': `Bearer ${this.config.apiKey}`,
'User-Agent': 'Prismatic-Plugin/1.0.0'
},
: this.config.timeout
};
// Transform response to standard format
const result = this.transformResponseresponse.data;
return {
: true,
: result.confidence,
: result.data,
: {
: 'custom-threat-feed',
: new Date.toISOString,
: response.timing.total,
: response.headers'x-ratelimit-remaining'
}
};
} catcherror {
return {
: false,
: {
: error.code || 'UNKNOWN_ERROR',
: error.message,
: this.isRetryableErrorerror
}
};
}
}
private transformResponse(rawData: any): TransformedResult {
// Implement your transformation logic
return {
: this.calculateConfidencerawData,
: {
: rawData.category,
: rawData.severity_level,
: new DaterawData.first_observed,
: new DaterawData.last_observed,
: rawData.tags ||,
: {
: rawData.country_code,
: rawData.autonomous_system,
: rawData.reputation?.score
}
}
};
}
private calculateConfidence(data: any): number {
// Implement confidence scoring logic
let confidence = 0.5; // Base confidence
ifdata.verified confidence += 0.3;
ifdata.source_count > 1 confidence += 0.2;
ifdata.last_observed_days < 7 confidence += 0.1;
return Math.minconfidence, 1.0;
}
async healthCheck(): Promise<HealthStatus> {
try {
const response = await this.httpClient.get'/health', {
: 5000
};
return {
: 'healthy',
: response.timing.total,
: response.headers'x-ratelimit-remaining'
};
} catcherror {
return {
: 'unhealthy',
: error.message
};
}
}
}3. Add Comprehensive Testing
// tests/adapter.test.ts
import { CustomThreatFeedAdapter } from '../src/adapter';
import { mockHttpClient } from '@prismatic-platform/plugin-kit/testing';
describe('CustomThreatFeedAdapter', () => {
let adapter: CustomThreatFeedAdapter;
let mockHttp: ReturnType<typeof mockHttpClient>;
beforeEach() => {
mockHttp = mockHttpClient;
adapter = new CustomThreatFeedAdapter{
: 'test-api-key',
: 'https://api.threat-feed.com',
: 10000
}, mockHttp;
};
describe'execute', () => {
it'should process IP address queries successfully', async () => {
// Mock successful API response
mockHttp.get.mockResolvedValue{
: {
: 'malware',
: 'high',
: true,
: 3,
: '2024-01-15T10:30:00Z',
: '2024-02-20T15:45:00Z',
: 'US',
: {: 0.85 }
},
: {: 150 },
: { 'x-ratelimit-remaining': '95' }
};
const result = await adapter.execute{
: '192.168.1.1',
: 'ip'
};
expectresult.success.toBetrue;
expectresult.confidence.toBeGreaterThan0.8;
expectresult.data.threat_type.toBe'malware';
expectresult.metadata.source.toBe'custom-threat-feed';
};
it'should handle API errors gracefully', async () => {
mockHttp.get.mockRejectedValue{
: 'RATE_LIMIT_EXCEEDED',
: 'Too many requests'
};
const result = await adapter.execute{
: '192.168.1.1',
: 'ip'
};
expectresult.success.toBefalse;
expectresult.error.code.toBe'RATE_LIMIT_EXCEEDED';
expectresult.error.retryable.toBetrue;
};
};
describe'healthCheck', () => {
it'should report healthy status', async () => {
mockHttp.get.mockResolvedValue{
: {: 75 },
: { 'x-ratelimit-remaining': '100' }
};
const health = await adapter.healthCheck;
expecthealth.status.toBe'healthy';
expecthealth.latency_ms.toBe75;
};
};
});
Advanced Plugin Development
Configuration Management
// config/schema.json - JSON Schema validation
{
"$schema""http://json-schema.org/draft-07/schema#",
"type""object",
"properties" {
"credentials": {
"type": "object",
"properties": {
"apiKey": {
"type": "string",
"minLength": 20,
"description": "API authentication key",
"x-secret": true
},
"username": {
"type": "string",
"description": "Username for basic auth"
}
},
"required":"apiKey"
},
"behavior": {
"type": "object",
"properties": {
"timeout": {
"type": "integer",
"minimum": 1000,
"maximum": 300000,
"default": 30000
},
"retries": {
"type": "integer",
"minimum": 0,
"maximum": 10,
"default": 3
},
"cacheTTL": {
"type": "integer",
"minimum": 0,
"default": 300000
}
}
}
},
"required""credentials"
}Error Handling Patterns
// src/error-handling.ts
import { PluginError, ErrorType } from '@prismatic-platform/plugin-kit';
export class CustomPluginError extends PluginError {
constructor(
public readonly type: ErrorType,
message: string,
public readonly retryable: boolean = false,
public readonly retryAfter?: number
) {
supertype, message;
}
}
export function handleApiError(error: any): CustomPluginError {
switcherror.status {
case 401:
return new CustomPluginError
'AUTHENTICATION_ERROR',
'Invalid API key or expired credentials',
false
;
case 429:
return new CustomPluginError
'RATE_LIMIT_EXCEEDED',
'API rate limit exceeded',
true,
parseInterror.headers'retry-after' || '60'
;
case 503:
return new CustomPluginError
'SERVICE_UNAVAILABLE',
'Upstream service temporarily unavailable',
true,
30
;
default:
return new CustomPluginError
'UNKNOWN_ERROR',
error.message || 'Unknown error occurred',
true
;
}
}Performance Optimization
// src/performance.ts
import { LRUCache } from 'lru-cache';
import { RateLimiter } from '@prismatic-platform/plugin-kit';
export class PerformanceOptimizedAdapter extends PluginAdapter {
private cache = new LRUCache<string, QueryResult>({
: 1000,
: this.config.cacheTTL
});
private rateLimiter = new RateLimiter({
: 100,
: 60000 // per minute
});
async execute(query: QueryInput): Promise<QueryResult> {
// Rate limiting
await this.rateLimiter.removeTokens1;
// Cache check
const cacheKey = this.generateCacheKeyquery;
const cached = this.cache.getcacheKey;
ifcached {
return {
...cached,
: {
...cached.metadata,
: true
}
};
}
// Execute query
const result = await this.executeQueryquery;
// Cache successful results
ifresult.success && result.confidence > 0.7 {
this.cache.setcacheKey, result;
}
return result;
}
private generateCacheKey(query: QueryInput): string {
return `${query.type}:${query.indicator}:${JSON.stringify.}`;
}
}
Plugin Testing Framework
Contract Testing
// tests/contract.test.ts
import { PluginContractTest } from '@prismatic-platform/plugin-kit/testing';
import { CustomThreatFeedAdapter } from '../src/adapter';
describe('Plugin Contract Tests', () => {
const contractTest = new PluginContractTestCustomThreatFeedAdapter;
it'should conform to plugin interface', async () => {
await contractTest.validateInterface;
};
it'should handle all required query types', async () => {
const queryTypes ='domain', 'ip', 'hash';
await contractTest.validateQueryTypesqueryTypes;
};
it'should return consistent response format', async () => {
await contractTest.validateResponseFormat;
};
it'should handle rate limiting correctly', async () => {
await contractTest.validateRateLimiting;
};
it'should implement health check', async () => {
await contractTest.validateHealthCheck;
};
});Integration Testing
// tests/integration.test.ts
describe('Integration Tests', () => {
let testServer: TestServer;
let adapter: CustomThreatFeedAdapter;
beforeAllasync () => {
// Start mock API server
testServer = new TestServer;
await testServer.start;
adapter = new CustomThreatFeedAdapter{
: 'test-key',
: testServer.url,
: 5000
};
};
afterAllasync () => {
await testServer.stop;
};
it'should handle real API responses', async () => {
// Set up mock responses
testServer.mockResponse'/indicators/ip/192.168.1.1', {
: 'botnet',
: 'medium',
: false
};
const result = await adapter.execute{
: '192.168.1.1',
: 'ip'
};
expectresult.success.toBetrue;
expectresult.data.threat_type.toBe'botnet';
};
});Performance Testing
// tests/performance.test.ts
describe('Performance Tests', () => {
it'should handle concurrent requests', async () => {
const promises = Array.from{: 100 }, (_, i) =>
adapter.execute{: `192.168.1.${i}`,: 'ip' }
;
const startTime = Date.now;
const results = await Promise.allpromises;
const duration = Date.now - startTime;
expectresults.toHaveLength100;
expectduration.toBeLessThan10000; // Under 10 seconds
expectresults.filterr => r.success.toHaveLength100;
};
it'should respect rate limits', async () => {
const adapter = new CustomThreatFeedAdapter{
: 'test-key',
: 'https://api.test.com'
};
// Simulate rate limit exceeded
mockHttp.get.mockRejectedValueOnce{
: 429,
: { 'retry-after': '1' }
};
const result = await adapter.execute{
: '192.168.1.1',
: 'ip'
};
expectresult.success.toBefalse;
expectresult.error.retryable.toBetrue;
};
});
Plugin Deployment
Local Development
# Development server with hot reload
npm run dev
# Run tests with coverage
npm run test:coverage
# Lint and format code
npm run lint
npm run format
# Build production version
npm run buildDocker Deployment
# docker/Dockerfile
FROM node:18-alpine
WORKDIR /app
# Copy package files
COPY package*.json ./
RUN npm ci --only=production
# Copy source code
COPY dist/ ./dist/
COPY config/ ./config/
# Create non-root user
RUN addgroup -g 1001 -S prismatic && \
adduser -S prismatic -u 1001
USER prismatic
EXPOSE 3000
CMD ["node", "dist/index.js"]Plugin Registry
# Register plugin with Prismatic registry
prismatic-plugin publish --config prismatic.config.js
# Install published plugin
prismatic-plugin install custom-threat-feed@1.0.0
# Update plugin
prismatic-plugin update custom-threat-feed
# List installed plugins
prismatic-plugin list
Community Plugins
Popular Community Plugins
OSINT Adapters:
@community/shodan-analyzer- Shodan API integration@community/virustotal-enhanced- Enhanced VirusTotal queries@community/censys-scanner- Censys Internet scanning@community/securitytrails-dns- DNS intelligence from SecurityTrails
Threat Intelligence:
@community/misp-connector- MISP threat sharing platform@community/otx-pulses- AlienVault OTX pulse integration@community/yara-scanner- YARA rule matching engine@community/hybrid-analysis- Hybrid Analysis sandbox API
Analysis Pipelines:
@community/ml-classifier- Machine learning threat classification@community/graph-analyzer- Network graph analysis@community/pattern-matcher- Advanced pattern recognition@community/risk-scorer- Custom risk scoring algorithms
Plugin Certification
Community Certification Process:
- Code Review: Security and quality assessment
- Performance Testing: Latency and throughput validation
- Documentation Review: API docs and usage examples
- Security Audit: Vulnerability and dependency analysis
- Integration Testing: Compatibility with platform versions
Certified Plugin Benefits:
- ✅ Featured in plugin marketplace
- ✅ Priority support from community
- ✅ Listed in official documentation
- ✅ Eligible for bounty rewards
- ✅ Commercial usage licensing
Plugin Development Tools
CLI Tools
# Plugin development CLI
npx @prismatic-platform/plugin-kit --help
# Commands available:
prismatic-plugin init <name> # Create new plugin
prismatic-plugin validate # Validate plugin structure
prismatic-plugin test # Run test suite
prismatic-plugin build # Build production version
prismatic-plugin publish # Publish to registry
prismatic-plugin docs # Generate documentationVS Code Extension
Prismatic Plugin Developer Extension:
- Syntax highlighting for plugin configs
- IntelliSense for plugin API
- Integrated testing and debugging
- Schema validation and error detection
- Code snippets and templates
Plugin Inspector
// Debug and inspect plugin behavior
import { PluginInspector } from '@prismatic-platform/plugin-kit/dev-tools';
const inspector = new PluginInspector(customThreatFeed);
// Inspect plugin metadata
console.log(inspector.getMetadata());
// Test query with detailed logging
await inspector.testQuery({
: '192.168.1.1',
: 'ip'
}, {
: true,
: true
});
// Generate performance report
const report = inspector.generateReport();
console.log(report.averageLatency);
console.log(report.successRate);
Best Practices & Guidelines
Code Quality Standards
Mandatory Requirements:
- ✅ TypeScript with strict mode enabled
- ✅ 100% test coverage for adapter logic
- ✅ ESLint and Prettier configuration
- ✅ Comprehensive error handling
- ✅ Rate limiting implementation
- ✅ Security vulnerability scanning
Security Considerations
Authentication Security:
// Secure credential handling
class SecureAdapter extends PluginAdapter {
constructor(config: PluginConfig) {
super{
...config,
// Never log sensitive data
: '[REDACTED]'
};
// Validate API key format
this.validateCredentialsconfig.credentials;
}
private validateCredentials(creds: any): void {
if!creds.apiKey || creds.apiKey.length < 20 {
throw new Error'Invalid API key format';
}
// Check for common credential leaks
ifcreds.apiKey.includes'test' || creds.apiKey.includes'demo' {
console.warn'Warning: Using test/demo credentials';
}
}
}Performance Guidelines
Response Time Targets:
- Health checks: < 1 second
- Simple queries: < 5 seconds
- Complex analysis: < 30 seconds
- Batch operations: < 2 minutes
Memory Usage:
- Maximum 512MB per plugin instance
- Automatic cleanup of cached data
- Streaming for large datasets
- Memory leak detection in tests
Ready to build your first plugin?
Get Started with Plugin Kit → Browse Community Plugins → Join Plugin Developers →
Dive deeper into the Prismatic Platform -- explore our architecture, agents, and epistemic framework.