Skip to content

Add plugin ecosystem protocol for vendor interoperability#374

Merged
hotlong merged 8 commits intomainfrom
copilot/create-plugin-architecture-doc
Jan 30, 2026
Merged

Add plugin ecosystem protocol for vendor interoperability#374
hotlong merged 8 commits intomainfrom
copilot/create-plugin-architecture-doc

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Jan 30, 2026

Establishes standardized protocols for plugin discovery, capability declaration, and cross-vendor interoperability in the ObjectStack microkernel architecture.

Core Protocols

Plugin Capability Manifest (system/plugin-capability.zod.ts)

  • Protocol implementation: Declare conformance levels (full/partial/experimental/deprecated) with certification support
  • Interface contracts: Define service methods, events, and stability guarantees
  • Dependency resolution: SemVer constraints with required capability validation
  • Extension points: 7 types (action/hook/widget/provider/transformer/validator/decorator) with cardinality control

Plugin Registry (hub/plugin-registry.zod.ts)

  • Vendor trust levels (official/verified/community/unverified)
  • Quality metrics (test coverage, documentation score, security scan results)
  • Conformance test tracking per protocol
  • Search/filter by protocols, categories, trust level, ratings

Naming Convention

Distinguishes package vs. code-level identifiers:

  • Packages (plugins, protocols): kebab-case with reverse domain → com.acme.crm.customer-management
  • Code (interfaces, extensions): snake_case → contact_service, customer_validator

Interoperability Patterns

// Protocol Implementation
capabilities: {
  implements: [{
    protocol: { id: 'com.objectstack.protocol.storage.v1', version: { major: 1, minor: 0, patch: 0 } },
    conformance: 'full',
    certified: true
  }],
  
  // Interface Provision
  provides: [{
    id: 'com.acme.crm.interface.customer_service',
    methods: [{ name: 'getCustomer', async: true, returnType: 'Customer' }],
    events: [{ name: 'customerCreated', payload: 'Customer' }]
  }],
  
  // Dependency with capability requirements
  requires: [{
    pluginId: 'com.objectstack.driver.postgres',
    version: '^1.0.0',
    requiredCapabilities: ['com.objectstack.protocol.storage.v1']
  }],
  
  // Extension points
  extensionPoints: [{
    id: 'com.acme.crm.extension.customer_validator',
    type: 'validator',
    cardinality: 'multiple',
    contract: { input: 'Customer', output: 'ValidationResult' }
  }]
}

Documentation

All documentation unified in English:

  • Architecture guide: /content/docs/developers/plugin-ecosystem.mdx
  • Implementation summary: /IMPLEMENTATION_SUMMARY.md
  • Reference implementation: /examples/plugin-advanced-crm/

Integration

Extends ManifestSchema with optional capabilities field for backward compatibility. Registry schemas exported via @objectstack/spec/hub.

Original prompt

你顶牛的微内核系统架构师,我所有的功能都是用插件开发的,如何表达一个插件实现的具体协议以及实现的程度,包括在整个生态中插件可能是需要互相调用的,如何确定这个命名规范,如何确保不同厂商编写的插件能够互相调用互相协作,如何构建这个生态帮我编写设计文档


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@vercel
Copy link
Copy Markdown

vercel bot commented Jan 30, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jan 30, 2026 5:47am

Request Review

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Copilot AI changed the title [WIP] Draft design document for plugin architecture Add plugin ecosystem protocol for vendor interoperability Jan 30, 2026
Copilot AI requested a review from hotlong January 30, 2026 02:01
@hotlong
Copy link
Copy Markdown
Contributor

hotlong commented Jan 30, 2026

@copilot 所有文档统一用英文

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Jan 30, 2026

@copilot 所有文档统一用英文

Done! All documentation has been unified to English only (commit 5e0ae52):

  • ❌ Removed PLUGIN_ECOSYSTEM_DESIGN_CN.md
  • ✅ Converted plugin-ecosystem.mdx to English-only (841→776 lines)
  • ✅ Converted IMPLEMENTATION_SUMMARY.md to English-only

All tests passing (1,822/1,822) and build successful.

@github-actions github-actions bot added documentation Improvements or additions to documentation protocol:system tests labels Jan 30, 2026
@github-actions
Copy link
Copy Markdown
Contributor

This PR is very large. Consider breaking it into smaller PRs for easier review.

@hotlong hotlong marked this pull request as ready for review January 30, 2026 05:46
Copilot AI review requested due to automatic review settings January 30, 2026 05:46
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request establishes a comprehensive plugin ecosystem protocol for ObjectStack, enabling standardized interoperability between plugins from different vendors. The PR introduces robust capability declaration, protocol conformance tracking, and plugin registry mechanisms.

Changes:

  • Introduces Plugin Capability Protocol schemas for protocol implementation, interface provision, dependency declaration, and extension points
  • Adds Plugin Registry schemas for discovery, quality metrics, and vendor trust management
  • Integrates capabilities into the existing ManifestSchema for backward compatibility
  • Provides comprehensive documentation and reference implementation

Reviewed changes

Copilot reviewed 34 out of 34 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/spec/src/system/plugin-capability.zod.ts Core protocol schemas defining capability conformance, protocol references, interfaces, dependencies, and extension points
packages/spec/src/system/plugin-capability.test.ts Comprehensive test coverage for all plugin capability schemas
packages/spec/src/hub/plugin-registry.zod.ts Registry schemas for plugin discovery, vendor verification, quality metrics, and search/filtering
packages/spec/src/system/manifest.zod.ts Integration of optional capabilities field into existing manifest schema
packages/spec/src/system/index.ts Export addition for plugin-capability schemas
packages/spec/src/hub/index.ts Export addition for plugin-registry schemas
packages/spec/json-schema/system/*.json Auto-generated JSON schemas for all new TypeScript schemas
packages/spec/json-schema/hub/*.json Auto-generated JSON schemas for registry types
examples/plugin-advanced-crm/objectstack.config.ts Reference implementation demonstrating all capability features
examples/plugin-advanced-crm/README.md Documentation explaining the example implementation
content/docs/developers/plugin-ecosystem.mdx Comprehensive architecture guide (776 lines)
content/docs/references/system/plugin-capability.mdx Schema reference documentation
content/docs/references/hub/plugin-registry.mdx Registry schema reference documentation
content/docs/references/system/meta.json Navigation metadata update
content/docs/references/hub/meta.json Navigation metadata update
content/docs/developers/meta.json Navigation metadata update

Comment on lines +1 to +412
import { z } from 'zod';
import { PluginCapabilityManifestSchema } from '../system/plugin-capability.zod';

/**
* # Plugin Registry Protocol
*
* Defines the schema for the plugin discovery and registry system.
* This enables plugins from different vendors to be discovered, validated,
* and composed together in the ObjectStack ecosystem.
*/

/**
* Plugin Vendor Information
*/
export const PluginVendorSchema = z.object({
/**
* Vendor identifier (reverse domain notation)
* Example: "com.acme", "org.apache", "com.objectstack"
*/
id: z.string()
.regex(/^[a-z][a-z0-9]*(\.[a-z][a-z0-9]*)+$/)
.describe('Vendor identifier (reverse domain)'),

/**
* Vendor display name
*/
name: z.string(),

/**
* Vendor website
*/
website: z.string().url().optional(),

/**
* Contact email
*/
email: z.string().email().optional(),

/**
* Verification status
*/
verified: z.boolean().default(false).describe('Whether vendor is verified by ObjectStack'),

/**
* Trust level
*/
trustLevel: z.enum(['official', 'verified', 'community', 'unverified']).default('unverified'),
});

/**
* Plugin Quality Metrics
*/
export const PluginQualityMetricsSchema = z.object({
/**
* Test coverage percentage
*/
testCoverage: z.number().min(0).max(100).optional(),

/**
* Documentation score (0-100)
*/
documentationScore: z.number().min(0).max(100).optional(),

/**
* Code quality score (0-100)
*/
codeQuality: z.number().min(0).max(100).optional(),

/**
* Security scan status
*/
securityScan: z.object({
lastScanDate: z.string().datetime().optional(),
vulnerabilities: z.object({
critical: z.number().int().min(0).default(0),
high: z.number().int().min(0).default(0),
medium: z.number().int().min(0).default(0),
low: z.number().int().min(0).default(0),
}).optional(),
passed: z.boolean().default(false),
}).optional(),

/**
* Conformance test results
*/
conformanceTests: z.array(z.object({
protocolId: z.string().describe('Protocol being tested'),
passed: z.boolean(),
totalTests: z.number().int().min(0),
passedTests: z.number().int().min(0),
lastRunDate: z.string().datetime().optional(),
})).optional(),
});

/**
* Plugin Usage Statistics
*/
export const PluginStatisticsSchema = z.object({
/**
* Total downloads
*/
downloads: z.number().int().min(0).default(0),

/**
* Downloads in the last 30 days
*/
downloadsLastMonth: z.number().int().min(0).default(0),

/**
* Number of active installations
*/
activeInstallations: z.number().int().min(0).default(0),

/**
* User ratings
*/
ratings: z.object({
average: z.number().min(0).max(5).default(0),
count: z.number().int().min(0).default(0),
distribution: z.object({
'5': z.number().int().min(0).default(0),
'4': z.number().int().min(0).default(0),
'3': z.number().int().min(0).default(0),
'2': z.number().int().min(0).default(0),
'1': z.number().int().min(0).default(0),
}).optional(),
}).optional(),

/**
* GitHub stars (if open source)
*/
stars: z.number().int().min(0).optional(),

/**
* Number of dependent plugins
*/
dependents: z.number().int().min(0).default(0),
});

/**
* Plugin Registry Entry
* Complete metadata for a plugin in the registry.
*/
export const PluginRegistryEntrySchema = z.object({
/**
* Plugin identifier (must match manifest.id)
*/
id: z.string()
.regex(/^([a-z][a-z0-9]*\.)+[a-z][a-z0-9-]+$/)
.describe('Plugin identifier (reverse domain notation)'),

/**
* Current version
*/
version: z.string().regex(/^\d+\.\d+\.\d+$/),

/**
* Plugin display name
*/
name: z.string(),

/**
* Short description
*/
description: z.string().optional(),

/**
* Detailed documentation/README
*/
readme: z.string().optional(),

/**
* Plugin type/category
*/
category: z.enum([
'data', // Data management, storage, databases
'integration', // External service integrations
'ui', // UI components and themes
'analytics', // Analytics and reporting
'security', // Security, auth, compliance
'automation', // Workflows and automation
'ai', // AI/ML capabilities
'utility', // General utilities
'driver', // Database/storage drivers
'gateway', // API gateways
'adapter', // Runtime adapters
]).optional(),

/**
* Tags for categorization
*/
tags: z.array(z.string()).optional(),

/**
* Vendor information
*/
vendor: PluginVendorSchema,

/**
* Capability manifest (what the plugin implements/provides)
*/
capabilities: PluginCapabilityManifestSchema.optional(),

/**
* Compatibility information
*/
compatibility: z.object({
/**
* Minimum ObjectStack version required
*/
minObjectStackVersion: z.string().optional(),

/**
* Maximum ObjectStack version supported
*/
maxObjectStackVersion: z.string().optional(),

/**
* Node.js version requirement
*/
nodeVersion: z.string().optional(),

/**
* Supported platforms
*/
platforms: z.array(z.enum(['linux', 'darwin', 'win32', 'browser'])).optional(),
}).optional(),

/**
* Links and resources
*/
links: z.object({
homepage: z.string().url().optional(),
repository: z.string().url().optional(),
documentation: z.string().url().optional(),
bugs: z.string().url().optional(),
changelog: z.string().url().optional(),
}).optional(),

/**
* Media assets
*/
media: z.object({
icon: z.string().url().optional(),
logo: z.string().url().optional(),
screenshots: z.array(z.string().url()).optional(),
video: z.string().url().optional(),
}).optional(),

/**
* Quality metrics
*/
quality: PluginQualityMetricsSchema.optional(),

/**
* Usage statistics
*/
statistics: PluginStatisticsSchema.optional(),

/**
* License information
*/
license: z.string().optional().describe('SPDX license identifier'),

/**
* Pricing (if commercial)
*/
pricing: z.object({
model: z.enum(['free', 'freemium', 'paid', 'enterprise']),
price: z.number().min(0).optional(),
currency: z.string().default('USD').optional(),
billingPeriod: z.enum(['one-time', 'monthly', 'yearly']).optional(),
}).optional(),

/**
* Publication dates
*/
publishedAt: z.string().datetime().optional(),
updatedAt: z.string().datetime().optional(),

/**
* Deprecation status
*/
deprecated: z.boolean().default(false),
deprecationMessage: z.string().optional(),
replacedBy: z.string().optional().describe('Plugin ID that replaces this one'),

/**
* Feature flags
*/
flags: z.object({
experimental: z.boolean().default(false),
beta: z.boolean().default(false),
featured: z.boolean().default(false),
verified: z.boolean().default(false),
}).optional(),
});

/**
* Plugin Search Filters
*/
export const PluginSearchFiltersSchema = z.object({
/**
* Search query
*/
query: z.string().optional(),

/**
* Filter by category
*/
category: z.array(z.string()).optional(),

/**
* Filter by tags
*/
tags: z.array(z.string()).optional(),

/**
* Filter by vendor trust level
*/
trustLevel: z.array(z.enum(['official', 'verified', 'community', 'unverified'])).optional(),

/**
* Filter by protocols implemented
*/
implementsProtocols: z.array(z.string()).optional(),

/**
* Filter by pricing model
*/
pricingModel: z.array(z.enum(['free', 'freemium', 'paid', 'enterprise'])).optional(),

/**
* Minimum rating
*/
minRating: z.number().min(0).max(5).optional(),

/**
* Sort options
*/
sortBy: z.enum([
'relevance',
'downloads',
'rating',
'updated',
'name',
]).optional(),

/**
* Sort order
*/
sortOrder: z.enum(['asc', 'desc']).default('desc').optional(),

/**
* Pagination
*/
page: z.number().int().min(1).default(1).optional(),
limit: z.number().int().min(1).max(100).default(20).optional(),
});

/**
* Plugin Installation Configuration
*/
export const PluginInstallConfigSchema = z.object({
/**
* Plugin identifier to install
*/
pluginId: z.string(),

/**
* Version to install (supports semver ranges)
*/
version: z.string().optional().describe('Defaults to latest'),

/**
* Plugin-specific configuration values
*/
config: z.record(z.any()).optional(),

/**
* Whether to auto-update
*/
autoUpdate: z.boolean().default(false).optional(),

/**
* Installation options
*/
options: z.object({
/**
* Skip dependency installation
*/
skipDependencies: z.boolean().default(false).optional(),

/**
* Force reinstall
*/
force: z.boolean().default(false).optional(),

/**
* Installation target
*/
target: z.enum(['system', 'space', 'user']).default('space').optional(),
}).optional(),
});

// Export types
export type PluginVendor = z.infer<typeof PluginVendorSchema>;
export type PluginQualityMetrics = z.infer<typeof PluginQualityMetricsSchema>;
export type PluginStatistics = z.infer<typeof PluginStatisticsSchema>;
export type PluginRegistryEntry = z.infer<typeof PluginRegistryEntrySchema>;
export type PluginSearchFilters = z.infer<typeof PluginSearchFiltersSchema>;
export type PluginInstallConfig = z.infer<typeof PluginInstallConfigSchema>;
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PluginRegistryEntrySchema and related schemas lack test coverage. While plugin-capability.zod.ts has comprehensive tests in plugin-capability.test.ts, the plugin-registry.zod.ts file (413 lines) does not have a corresponding test file. This is inconsistent with the testing patterns seen in the system directory where most schema files have accompanying test files (e.g., manifest.test.ts, plugin.test.ts, datasource.test.ts).

Copilot uses AI. Check for mistakes.
@hotlong hotlong merged commit ed1dfe5 into main Jan 30, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation protocol:system size/xl tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants