Successfully implemented the ObjectOS layer - a new @objectstack/objectos package containing system runtime object definitions that represent metadata as queryable data.
Based on architectural discussions, we established:
-
Location:
packages/objectos(NOTpackages/plugins/plugin-system)- Rationale: System objects are core infrastructure, not optional plugins
- ObjectOS represents the OS-level primitives of the platform
-
Dual-Table Pattern: Keep BOTH systems (do NOT deprecate
sys_metadata)sys_metadata: Source of truth for package management, version control, deployment- Type-specific tables (
sys_object,sys_view, etc.): Queryable data for UI/reporting
packages/objectos/
├── src/
│ ├── objects/
│ │ ├── sys-metadata.object.ts # Generic metadata envelope
│ │ ├── sys-object.object.ts # Object definitions
│ │ ├── sys-view.object.ts # View definitions
│ │ ├── sys-agent.object.ts # AI Agent definitions
│ │ ├── sys-tool.object.ts # AI Tool definitions
│ │ ├── sys-flow.object.ts # Flow definitions
│ │ └── index.ts
│ ├── index.ts # Package entry point
│ └── registry.ts # System object registry
├── package.json
├── tsconfig.json
├── tsup.config.ts
└── README.md
- Purpose: Source of truth for package management
- Features: Version control, checksums, package ownership, deployment tracking
- Fields: 20+ fields including version, checksum, package_id, managed_by, scope
- Purpose: Browse/filter/search object definitions in Studio
- Features: Denormalized data, complex fields as JSON
- Fields: 30+ fields including fields_json, capabilities_json, field_count
- Purpose: Manage view metadata through Object Protocol
- Features: View type filtering, object references
- Fields: columns_json, filters_json, sort_json, config_json
- Purpose: AI agent configuration as data
- Features: Model config, tools/skills management
- Fields: model, temperature, system_prompt, tools_json, skills_json
- Purpose: AI tool registry as queryable data
- Features: Parameter schemas, handler code
- Fields: parameters_json, handler_code
- Purpose: Flow metadata management
- Features: Flow types, trigger configuration
- Fields: flow_type, nodes_json, edges_json, trigger_type
-
Metadata as Data
- All metadata types are queryable using Object Protocol
- Same CRUD operations as business data
- Consistent API:
/api/v1/data/sys_object,/api/v1/data/sys_view
-
Dual-Table Architecture
Package Loader ↓ sys_metadata (source of truth) ↓ (projection) sys_object, sys_view, etc. (queryable) ↓ Studio UI (auto-generated) -
Version Management
sys_metadatatracks all versionssys_metadata_historytable for history- Checksum-based change detection
- Package upgrade/downgrade support
-
Auto-Generated UI
- Studio uses Object Protocol
- No custom UI code per metadata type
- Leverage grid/form/kanban views
- Salesforce: CustomObject, CustomField (queryable metadata)
- ServiceNow: sys_db_object, sys_dictionary (table-based metadata)
- Kubernetes: CRDs as structured resources
- Update
packages/metadataservice to support projection - Implement dual-table sync logic
- Register system objects in runtime bootstrap
Implementation Details:
- Created
MetadataProjectorservice inpackages/metadata/src/projection/ - Integrated projection into
DatabaseLoader.save()andDatabaseLoader.delete() - Added projection functions for each metadata type: object, view, agent, tool, flow
- Updated
MetadataPluginto register all system objects from@objectstack/objectos - Projection is enabled by default, can be disabled via
enableProjection: falseoption
- Update Studio to query type-specific tables
- Use
/api/v1/data/sys_objectfor browsing - Auto-generate metadata forms
- Add comprehensive test coverage
- Update documentation
- Create migration guides
import { SystemObjects } from '@objectstack/objectos';
// Register all system objects during bootstrap
for (const [name, definition] of Object.entries(SystemObjects)) {
await kernel.metadata.register('object', name, definition, {
scope: 'system',
isSystem: true,
managedBy: 'platform',
});
}
// Query metadata using Object Protocol
const objects = await client.data.find('sys_object', {
filter: { namespace: 'crm' },
sort: 'name',
});
// Studio auto-generates UI
<GridView object="sys_object" />
<FormView object="sys_object" recordId="account" />- ✅ Unified Protocol: One protocol for both data and metadata
- ✅ Auto-Generated UI: Studio reuses existing components
- ✅ Better DX: Consistent API for all entity types
- ✅ Version Control: Full history via sys_metadata_history
- ✅ Package Management: Track ownership and deployments
- ✅ Industry Standard: Follows Salesforce/ServiceNow patterns
/home/runner/work/framework/framework/packages/objectos/package.json/home/runner/work/framework/framework/packages/objectos/tsconfig.json/home/runner/work/framework/framework/packages/objectos/tsup.config.ts/home/runner/work/framework/framework/packages/objectos/README.md/home/runner/work/framework/framework/packages/objectos/src/index.ts/home/runner/work/framework/framework/packages/objectos/src/registry.ts/home/runner/work/framework/framework/packages/objectos/src/objects/index.ts/home/runner/work/framework/framework/packages/objectos/src/objects/sys-metadata.object.ts/home/runner/work/framework/framework/packages/objectos/src/objects/sys-object.object.ts/home/runner/work/framework/framework/packages/objectos/src/objects/sys-view.object.ts/home/runner/work/framework/framework/packages/objectos/src/objects/sys-agent.object.ts/home/runner/work/framework/framework/packages/objectos/src/objects/sys-tool.object.ts/home/runner/work/framework/framework/packages/objectos/src/objects/sys-flow.object.ts
The ObjectOS package establishes a clean architectural foundation for treating metadata as queryable data. This enables auto-generated Studio UI, unified APIs, and follows industry best practices from Salesforce, ServiceNow, and Kubernetes.
The dual-table architecture preserves the benefits of sys_metadata for package management while adding queryability through type-specific tables.