diff --git a/docs/SPEC_REFACTORING.md b/docs/SPEC_REFACTORING.md index 83c4050e..e0cbf691 100644 --- a/docs/SPEC_REFACTORING.md +++ b/docs/SPEC_REFACTORING.md @@ -2,7 +2,10 @@ ## Overview -This document describes the refactoring of ObjectOS to align with the [@objectstack/spec](https://github.com/objectstack-ai/spec) protocol version 0.3.3. +This document describes the alignment of ObjectOS with the [@objectstack/spec](https://github.com/objectstack-ai/spec) protocol. + +**Current Version:** v0.4.1 (Updated: 2026-01-27) +**Previous Version:** v0.3.3 ## What is @objectstack/spec? @@ -24,31 +27,34 @@ The specification is organized into five namespaces: - `Query` (AST), `Driver` (Interface), `Datasource` - `Permission`, `Sharing`, `Flow` -### 2. Kernel Protocol (`@objectstack/spec/kernel`) -*Plugin System & Runtime* -- `Manifest` - Plugin configuration +### 2. System Protocol (`@objectstack/spec/system`) +*Plugin System, Runtime Infrastructure & Security* +- `Manifest` - Plugin configuration with contribution points - `Plugin` - Lifecycle hooks (onInstall, onEnable, onDisable, onUninstall) -- `Context` - Runtime context available to plugins +- `Context` - Runtime context available to plugins (KernelContext, PluginContextData) - `Logger` - Structured logging - -### 3. System Protocol (`@objectstack/spec/system`) -*Runtime Infrastructure & Security* - `Audit` - Audit logging and event tracking - `Events` - Event bus and handlers - `Job` - Scheduled jobs and background tasks -- `Translation` - I18n support -### 4. UI Protocol (`@objectstack/spec/ui`) +**Note:** In v0.4.1, the Kernel Protocol was merged into the System Protocol for better organization. + +### 3. UI Protocol (`@objectstack/spec/ui`) *Presentation & Interaction* - `App`, `Page`, `View` (Grid/Kanban) - `Dashboard` (Widgets), `Report` - `Action` (Triggers) -### 5. API Protocol (`@objectstack/spec/api`) +### 4. API Protocol (`@objectstack/spec/api`) *Connectivity & Contracts* - `Contract` (DTOs), `Endpoint` (Gateway) - `Discovery` (Metadata), `Realtime` (Socket) +### 5. Auth Protocol (`@objectstack/spec/auth`) +*Authentication & Authorization* +- `User`, `Session`, `Role` +- `Permission`, `Token` + ## Changes Made ### 1. Dependencies @@ -74,7 +80,7 @@ export type { PluginDefinition, PluginContextData, ObjectStackManifest, -} from '@objectstack/spec/kernel'; +} from '@objectstack/spec/system'; export type { ServiceObject, @@ -159,7 +165,7 @@ export const MyPlugin: ObjectQLPlugin = { **New Style (ObjectStack Spec Plugin):** ```typescript -import type { PluginDefinition, PluginContextData } from '@objectstack/spec/kernel'; +import type { PluginDefinition, PluginContextData } from '@objectstack/spec/system'; export const MyPlugin: PluginDefinition = { async onEnable(context: PluginContextData) { @@ -181,7 +187,7 @@ The API remains mostly unchanged. The main difference is better type safety: ```typescript import { ObjectOS } from '@objectos/kernel'; -import type { ObjectStackManifest } from '@objectstack/spec/kernel'; +import type { ObjectStackManifest } from '@objectstack/spec/system'; const os = new ObjectOS({ plugins: [MyPlugin], diff --git a/package-lock.json b/package-lock.json index 2c13429a..d04924c2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "@objectql/platform-node": "^3.0.1", "@objectql/starter-basic": "^1.8.4", "@objectql/starter-enterprise": "^1.8.4", - "@objectstack/spec": "0.3.3", + "@objectstack/spec": "0.4.1", "build": "^0.1.4" }, "devDependencies": { @@ -29,7 +29,7 @@ "js-yaml": "^4.1.1", "supertest": "^7.2.2", "ts-jest": "^29.4.6", - "typescript": "^5.3.0", + "typescript": "^5.9.3", "vitepress": "^1.6.4" } }, @@ -2320,9 +2320,9 @@ "license": "MIT" }, "node_modules/@objectstack/spec": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@objectstack/spec/-/spec-0.3.3.tgz", - "integrity": "sha512-GGSrRLECgYY1epLocdCkCsicerFKAKlRpluGmCqK1iVNgTgiC04zniLogYQXu5kf6UIB6mHQNBHcbr1x5DOmVQ==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@objectstack/spec/-/spec-0.4.1.tgz", + "integrity": "sha512-UEGjeZBgK0eAcShKOVYgDQ8+vekaRcgYSmJ09Avf3iyTzjl3sKqYC0WVQdyVWbqptMhU5kNlKEIIVxcdJnUc0Q==", "license": "Apache-2.0", "dependencies": { "zod": "^3.22.4" diff --git a/package.json b/package.json index 0b07aae4..87404ed0 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "@objectql/platform-node": "^3.0.1", "@objectql/starter-basic": "^1.8.4", "@objectql/starter-enterprise": "^1.8.4", - "@objectstack/spec": "0.3.3", + "@objectstack/spec": "0.4.1", "build": "^0.1.4" } } diff --git a/packages/kernel/CHANGELOG.md b/packages/kernel/CHANGELOG.md index 7f06fe9d..f11f9be7 100644 --- a/packages/kernel/CHANGELOG.md +++ b/packages/kernel/CHANGELOG.md @@ -1,5 +1,58 @@ # @objectos/kernel +## 0.2.1 (2026-01-27) + +### Minor Changes + +- **Protocol Upgrade**: Upgraded to @objectstack/spec v0.4.1 + - Updated all imports from `@objectstack/spec/kernel` to `@objectstack/spec/system` + - Plugin manifest schema updated to use `objects` glob patterns instead of inline `definitions` + - Added support for `contributes` section for extension points (actions, events, field types, etc.) + - Improved namespace organization following the new protocol structure + +### Breaking Changes + +- **Manifest Schema**: The plugin manifest structure has changed in v0.4.1 + - `definitions.objects` is no longer supported + - Use `objects: ['./objects/*.object.yml']` glob patterns to reference object files + - Use `contributes` section to register actions, events, and other extension points + +### Migration Guide + +If you have existing plugins, update your manifest from: + +```typescript +// Old (v0.3.3) +const manifest = { + id: 'com.example.plugin', + version: '1.0.0', + type: 'plugin', + name: 'My Plugin', + definitions: { + objects: { + my_object: { /* inline definition */ } + } + } +}; +``` + +To: + +```typescript +// New (v0.4.1) +const manifest = { + id: 'com.example.plugin', + version: '1.0.0', + type: 'plugin', + name: 'My Plugin', + objects: ['./objects/*.object.yml'], // Reference files with glob patterns + contributes: { + actions: [{ name: 'myAction', label: 'My Action' }], + events: ['my_object.created'] + } +}; +``` + ## 0.2.0 (2026-01-17) ### Minor Changes diff --git a/packages/kernel/README.md b/packages/kernel/README.md index 485385f3..11eafcec 100644 --- a/packages/kernel/README.md +++ b/packages/kernel/README.md @@ -6,7 +6,7 @@ The core runtime engine for ObjectOS - a metadata-driven platform built on the [ `@objectos/kernel` is the execution engine that powers ObjectOS. It extends ObjectQL with application-specific capabilities, providing: -- **Spec-Compliant Types**: Built on `@objectstack/spec` for protocol consistency +- **Spec-Compliant Types**: Built on `@objectstack/spec` v0.4.1 for protocol consistency - **Metadata Processing**: Parse and validate object definitions, apps, and data files - **Plugin Lifecycle**: Standardized hooks (onInstall, onEnable, onDisable, onUninstall) - **Permission Enforcement**: Apply role-based access control and field-level security @@ -15,11 +15,11 @@ The core runtime engine for ObjectOS - a metadata-driven platform built on the [ ## Protocol Compliance -This package implements the **@objectstack/spec** protocol: +This package implements the **@objectstack/spec v0.4.1** protocol: -- **Kernel Protocol** (`@objectstack/spec/kernel`): Plugin lifecycle, manifests, context +- **System Protocol** (`@objectstack/spec/system`): Plugin lifecycle, manifests, context, kernel infrastructure - **Data Protocol** (`@objectstack/spec/data`): Object schemas, fields, queries -- **System Protocol** (`@objectstack/spec/system`): Audit, events, jobs +- **API Protocol** (`@objectstack/spec/api`): REST/GraphQL contracts, endpoints, discovery All TypeScript types are imported from the spec to ensure consistency across the ecosystem. @@ -28,7 +28,7 @@ import type { PluginDefinition, PluginContextData, ObjectStackManifest -} from '@objectstack/spec/kernel'; +} from '@objectstack/spec/system'; import type { ServiceObject, diff --git a/packages/kernel/package.json b/packages/kernel/package.json index 6d48c953..2e6b9f17 100644 --- a/packages/kernel/package.json +++ b/packages/kernel/package.json @@ -11,7 +11,7 @@ "dependencies": { "@objectql/core": "^3.0.1", "@objectql/types": "^3.0.1", - "@objectstack/spec": "0.3.3", + "@objectstack/spec": "0.4.1", "fast-glob": "^3.3.2", "js-yaml": "^4.1.0" }, diff --git a/packages/kernel/src/examples/crm-plugin-example.ts b/packages/kernel/src/examples/crm-plugin-example.ts index 67862297..2c697241 100644 --- a/packages/kernel/src/examples/crm-plugin-example.ts +++ b/packages/kernel/src/examples/crm-plugin-example.ts @@ -3,7 +3,7 @@ */ import { ObjectOS } from '../objectos'; -import type { ObjectStackManifest, PluginDefinition } from '@objectstack/spec/kernel'; +import type { ObjectStackManifest, PluginDefinition } from '@objectstack/spec/system'; export const CRMManifest: ObjectStackManifest = { id: 'com.example.crm', @@ -12,37 +12,21 @@ export const CRMManifest: ObjectStackManifest = { name: 'Example CRM Plugin', description: 'A complete CRM plugin demonstrating spec compliance', permissions: ['system.user.read', 'system.data.write'], - definitions: { - objects: { - crm_lead: { - name: 'crm_lead', - label: 'Lead', - pluralLabel: 'Leads', - description: 'Sales lead tracking', - icon: 'user-plus', - active: true, - isSystem: false, - abstract: false, - datasource: 'default', - fields: { - name: { - type: 'text', - label: 'Lead Name', - required: true, - searchable: true, - multiple: false, - unique: false, - deleteBehavior: 'set_null', - hidden: false, - readonly: false, - encryption: false, - index: false, - externalId: false, - }, - }, - }, - }, - }, + // In v0.4.1, objects are defined via glob patterns pointing to object definition files + objects: ['./objects/*.object.yml'], + // Contribution points for extending the platform + contributes: { + // Register custom actions that can be invoked by flows or API + actions: [ + { + name: 'convertLead', + label: 'Convert Lead to Account', + description: 'Converts a lead to an account and contact', + } + ], + // Register custom events that this plugin listens to + events: ['lead.created', 'lead.converted'], + } }; export const CRMPlugin: PluginDefinition = { diff --git a/packages/kernel/src/kernel-context.ts b/packages/kernel/src/kernel-context.ts index 5781dbf4..6246defd 100644 --- a/packages/kernel/src/kernel-context.ts +++ b/packages/kernel/src/kernel-context.ts @@ -1,11 +1,11 @@ /** * Kernel Context Implementation * - * Implements the KernelContext interface from @objectstack/spec/kernel. + * Implements the KernelContext interface from @objectstack/spec/system. * Provides static environment information available at boot time. */ -import type { KernelContext } from '@objectstack/spec/kernel'; +import type { KernelContext } from '@objectstack/spec/system'; import { randomUUID } from 'crypto'; /** diff --git a/packages/kernel/src/logger.ts b/packages/kernel/src/logger.ts index 5dfde51f..f9d8a1e8 100644 --- a/packages/kernel/src/logger.ts +++ b/packages/kernel/src/logger.ts @@ -1,7 +1,7 @@ /** * Logger Implementation * - * Provides structured logging that conforms to the @objectstack/spec/kernel Logger interface. + * Provides structured logging that conforms to the @objectstack/spec/system Logger interface. */ export type LogLevel = 'debug' | 'info' | 'warn' | 'error'; diff --git a/packages/kernel/src/objectos.ts b/packages/kernel/src/objectos.ts index 8de5b9fa..31447623 100644 --- a/packages/kernel/src/objectos.ts +++ b/packages/kernel/src/objectos.ts @@ -1,6 +1,6 @@ import { ObjectQL } from '@objectql/core'; import { ObjectQLConfig, ObjectQLPlugin } from '@objectql/types'; -import type { PluginDefinition, ObjectStackManifest, KernelContext } from '@objectstack/spec/kernel'; +import type { PluginDefinition, ObjectStackManifest, KernelContext } from '@objectstack/spec/system'; import { ObjectOSPlugin } from './plugins/objectql'; import { KernelContextManager } from './kernel-context'; import { StorageManager } from './scoped-storage'; diff --git a/packages/kernel/src/plugin-context.ts b/packages/kernel/src/plugin-context.ts index eee256b3..eb7208ce 100644 --- a/packages/kernel/src/plugin-context.ts +++ b/packages/kernel/src/plugin-context.ts @@ -2,10 +2,10 @@ * Plugin Context Builder * * Creates PluginContext instances that provide plugins with access to - * ObjectStack APIs according to @objectstack/spec/kernel. + * ObjectStack APIs according to @objectstack/spec/system. */ -import type { PluginContextData } from '@objectstack/spec/kernel'; +import type { PluginContextData } from '@objectstack/spec/system'; import type { IObjectQL } from '@objectql/types'; import { Logger, createLogger } from './logger'; import { ScopedStorage } from './scoped-storage'; diff --git a/packages/kernel/src/plugin-manager.ts b/packages/kernel/src/plugin-manager.ts index 1b63ac39..e7e7fe72 100644 --- a/packages/kernel/src/plugin-manager.ts +++ b/packages/kernel/src/plugin-manager.ts @@ -1,7 +1,7 @@ /** * Plugin Manager * - * Manages the plugin lifecycle according to @objectstack/spec/kernel. + * Manages the plugin lifecycle according to @objectstack/spec/system. * Handles plugin registration, initialization, and lifecycle hooks. */ @@ -9,7 +9,7 @@ import type { PluginDefinition, PluginContextData, ObjectStackManifest -} from '@objectstack/spec/kernel'; +} from '@objectstack/spec/system'; import { Logger, createLogger } from './logger'; import { ScopedStorage } from './scoped-storage'; diff --git a/packages/kernel/src/plugins/example-spec-plugin.ts b/packages/kernel/src/plugins/example-spec-plugin.ts index e6312633..39d7392a 100644 --- a/packages/kernel/src/plugins/example-spec-plugin.ts +++ b/packages/kernel/src/plugins/example-spec-plugin.ts @@ -5,11 +5,11 @@ * ObjectStack specification for plugin lifecycle and context. */ -import type { PluginDefinition, PluginContextData, ObjectStackManifest } from '@objectstack/spec/kernel'; +import type { PluginDefinition, PluginContextData, ObjectStackManifest } from '@objectstack/spec/system'; /** * Plugin Manifest - * Conforms to @objectstack/spec/kernel/ManifestSchema + * Conforms to @objectstack/spec/system/ManifestSchema * * This is typically stored in a package.json or manifest.json file * and loaded by the kernel. For this example, we define it inline. @@ -24,74 +24,31 @@ export const ExampleCRMManifest: ObjectStackManifest = { 'system.user.read', 'system.data.write', ], - // Object files can be specified as glob patterns + // In v0.4.1, objects are defined via glob patterns pointing to object definition files + // Object files should be YAML or TypeScript files following the object schema objects: ['./objects/*.object.yml'], - // Or provided inline as compiled definitions - definitions: { - objects: { - 'crm_lead': { - name: 'crm_lead', - label: 'Lead', - pluralLabel: 'Leads', - description: 'Sales lead tracking', - icon: 'user-plus', - active: true, - isSystem: false, - abstract: false, - datasource: 'default', - fields: { - name: { - type: 'text', - label: 'Lead Name', - required: true, - searchable: true, - multiple: false, - unique: false, - deleteBehavior: 'set_null', - hidden: false, - readonly: false, - encryption: false, - index: false, - externalId: false, - }, - email: { - type: 'email', - label: 'Email', - required: true, - searchable: true, - unique: true, - multiple: false, - deleteBehavior: 'set_null', - hidden: false, - readonly: false, - encryption: false, - index: true, - externalId: false, - }, - status: { - type: 'select', - label: 'Status', - required: true, - searchable: true, - multiple: false, - unique: false, - deleteBehavior: 'set_null', - hidden: false, - readonly: false, - encryption: false, - index: false, - externalId: false, - options: [ - { label: 'New', value: 'new', default: true }, - { label: 'Contacted', value: 'contacted' }, - { label: 'Qualified', value: 'qualified' }, - { label: 'Converted', value: 'converted' }, - { label: 'Lost', value: 'lost' }, - ], - }, - }, - }, - }, + + // Contribution points for extending the platform + contributes: { + // Register custom actions that can be invoked by flows or API + actions: [ + { + name: 'convertLead', + label: 'Convert Lead to Account', + description: 'Converts a lead to an account and contact', + } + ], + // Register custom events that this plugin listens to + events: ['crm_lead.created', 'crm_lead.converted'], + + // Register custom field types + fieldTypes: [ + { + name: 'lead_status', + label: 'Lead Status', + description: 'Special field type for lead status with workflow integration', + } + ], }, }; @@ -103,7 +60,7 @@ export const ExampleCRMManifest: ObjectStackManifest = { * - Using the plugin context (ql, os, logger, storage, etc.) * - Registering routes and scheduled jobs * - * Conforms to @objectstack/spec/kernel/PluginLifecycleSchema + * Conforms to @objectstack/spec/system/PluginLifecycleSchema */ export const ExampleCRMPlugin: PluginDefinition = { @@ -125,7 +82,7 @@ export const ExampleCRMPlugin: PluginDefinition = { async onEnable(context: PluginContextData) { context.logger.info('CRM Plugin: Enabling...'); - // The metadata from ExampleCRMManifest.definitions is loaded by the kernel + // The metadata from object files (specified in manifest.objects) is loaded by the kernel // before this hook is called // Register custom routes @@ -226,20 +183,22 @@ export const ExampleCRMPlugin: PluginDefinition = { * await os.init(); * ``` * - * ## Plugin Architecture Notes + * ## Plugin Architecture Notes (v0.4.1) * - * In the ObjectStack spec, plugins are separated into two parts: + * In the ObjectStack spec v0.4.1, plugins are separated into two parts: * - * 1. **Manifest** (@objectstack/spec/kernel/ManifestSchema) + * 1. **Manifest** (@objectstack/spec/system/ManifestSchema) * - Static configuration (id, version, name, permissions) - * - Object definitions and metadata + * - Object file glob patterns (objects are defined in separate files) + * - Contribution points (actions, events, field types, etc.) * - Typically stored in package.json or manifest.json * - * 2. **Lifecycle Hooks** (@objectstack/spec/kernel/PluginLifecycleSchema) + * 2. **Lifecycle Hooks** (@objectstack/spec/system/PluginLifecycleSchema) * - Runtime behavior (onInstall, onEnable, onLoad, etc.) * - Executable code * - Typically exported from index.ts or main.js * * The kernel loads manifests first to understand what plugins are available, - * then executes lifecycle hooks at appropriate times. + * then loads object definitions from the files specified in manifest.objects, + * and finally executes lifecycle hooks at appropriate times. */ diff --git a/packages/kernel/src/scoped-storage.ts b/packages/kernel/src/scoped-storage.ts index d7013ae3..781de7e8 100644 --- a/packages/kernel/src/scoped-storage.ts +++ b/packages/kernel/src/scoped-storage.ts @@ -2,7 +2,7 @@ * Scoped Storage Implementation * * Provides plugin-scoped key-value storage that conforms to the - * @objectstack/spec/kernel ScopedStorage interface. + * @objectstack/spec/system ScopedStorage interface. */ /** diff --git a/packages/kernel/src/types.ts b/packages/kernel/src/types.ts index 68dd78da..f316c7d8 100644 --- a/packages/kernel/src/types.ts +++ b/packages/kernel/src/types.ts @@ -7,7 +7,7 @@ // Re-export core protocol types from @objectstack/spec export type { - // Kernel Protocol + // System Protocol (formerly kernel protocol) ObjectStackManifest, PluginDefinition, PluginLifecycleHooks, @@ -17,7 +17,7 @@ export type { LogEntry, LogLevel, LogFormat, -} from '@objectstack/spec/kernel'; +} from '@objectstack/spec/system'; export type { // Data Protocol diff --git a/packages/kernel/test/plugin-manager.test.ts b/packages/kernel/test/plugin-manager.test.ts index 09443f7c..34317c9b 100644 --- a/packages/kernel/test/plugin-manager.test.ts +++ b/packages/kernel/test/plugin-manager.test.ts @@ -3,7 +3,7 @@ */ import { PluginManager } from '../src/plugin-manager'; -import type { ObjectStackManifest, PluginDefinition, PluginContextData } from '@objectstack/spec/kernel'; +import type { ObjectStackManifest, PluginDefinition, PluginContextData } from '@objectstack/spec/system'; describe('PluginManager', () => { let pluginManager: PluginManager; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6044ee80..f25d3986 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -27,8 +27,8 @@ importers: specifier: ^1.8.4 version: 1.8.4(@objectql/core@3.0.1(encoding@0.1.13)(ws@8.19.0)(zod@3.25.76))(@objectql/driver-sql@3.0.1(sqlite3@5.1.7))(@objectql/platform-node@3.0.1(encoding@0.1.13)(ws@8.19.0)(zod@3.25.76))(@objectql/types@3.0.1)(sqlite3@5.1.7) '@objectstack/spec': - specifier: 0.3.3 - version: 0.3.3 + specifier: 0.4.1 + version: 0.4.1 build: specifier: ^0.1.4 version: 0.1.4 @@ -137,8 +137,8 @@ importers: specifier: ^3.0.1 version: 3.0.1 '@objectstack/spec': - specifier: 0.3.3 - version: 0.3.3 + specifier: 0.4.1 + version: 0.4.1 fast-glob: specifier: ^3.3.2 version: 3.3.3 @@ -1581,6 +1581,10 @@ packages: resolution: {integrity: sha512-GGSrRLECgYY1epLocdCkCsicerFKAKlRpluGmCqK1iVNgTgiC04zniLogYQXu5kf6UIB6mHQNBHcbr1x5DOmVQ==} engines: {node: '>=18.0.0'} + '@objectstack/spec@0.4.1': + resolution: {integrity: sha512-UEGjeZBgK0eAcShKOVYgDQ8+vekaRcgYSmJ09Avf3iyTzjl3sKqYC0WVQdyVWbqptMhU5kNlKEIIVxcdJnUc0Q==} + engines: {node: '>=18.0.0'} + '@orama/orama@3.1.18': resolution: {integrity: sha512-a61ljmRVVyG5MC/698C8/FfFDw5a8LOIvyOLW5fztgUXqUpc1jOfQzOitSCbge657OgXXThmY3Tk8fpiDb4UcA==} engines: {node: '>= 20.0.0'} @@ -8391,6 +8395,10 @@ snapshots: dependencies: zod: 3.25.76 + '@objectstack/spec@0.4.1': + dependencies: + zod: 3.25.76 + '@orama/orama@3.1.18': {} '@oxc-transform/binding-android-arm64@0.105.0':