All notable changes to the ObjectStack Protocol will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
@objectstack/driver-tursoplugin — Migrated and standardized the Turso/libSQL driver from@objectql/driver-tursointopackages/plugins/driver-turso/. The driver extendsSqlDriverfrom@objectstack/driver-sql— all CRUD, schema, filter, aggregation, and introspection logic is inherited with zero code duplication. Turso-specific features include: three connection modes (local file, in-memory, embedded replica),@libsql/clientsync mechanism for embedded replicas, multi-tenant router with TTL-based driver caching, and enhanced capability flags (FTS5, JSON1, CTE, savepoints, indexes). Includes 53 unit tests. Factory functioncreateTursoDriver()and plugin manifest for kernel integration.- Multi-tenant routing (
createMultiTenantRouter) — Database-per-tenant architecture with automatic driver lifecycle management, tenant ID validation, configurable TTL cache, andonTenantCreate/onTenantEvictlifecycle callbacks. Serverless-safe (no global intervals).
@objectstack/driver-sql— Protected extensibility — Changedprivatetoprotectedfor all internal properties and methods (knex,config,jsonFields,booleanFields,tablesWithTimestamps,isSqlite,isPostgres,isMysql,getBuilder,applyFilters,applyFilterCondition,mapSortField,mapAggregateFunc,buildWindowFunction,createColumn,ensureDatabaseExists,createDatabase,isJsonField,formatInput,formatOutput,introspectColumns,introspectForeignKeys,introspectPrimaryKeys,introspectUniqueConstraints). Enables clean subclassing for driver variants (Turso, D1, etc.) without code duplication.
@objectstack/driver-sql—count()returns NaN for zero results — Fixedcount()method using||(logical OR) instead of??(nullish coalescing) to read the count value. When the actual count was0,row.count || row['count(*)']evaluated toNumber(undefined)=NaNbecause0is falsy. Now usesrow.count ?? row['count(*)'] ?? 0for correct zero handling.
- Unified Data Driver Contract (
IDataDriver) — Resolved the split betweenDriverInterface(core, minimal ~13 methods) andIDataDriver(spec, comprehensive 28 methods).IDataDriverfrom@objectstack/spec/contractsis now the single authoritative contract for all database driver implementations.DriverInterfaceis retained as a deprecated type alias for backward compatibility. Both@objectstack/driver-sqland@objectstack/driver-memorynow implementIDataDriverdirectly with fullDriverCapabilitiessupport. @objectstack/driver-sql— Added missingIDataDrivermethods:findStream,upsert,bulkUpdate,bulkDelete,commit,rollback,dropTable,explain. Alignedsupportswith fullDriverCapabilitiesschema.updateMany/deleteManynow returnnumber(count) instead of{ modifiedCount }/{ deletedCount }objects.deletereturnsboolean.@objectstack/driver-memory— Alignedsupportsproperty with fullDriverCapabilitiesschema (addedcreate,read,update,delete,bulkCreate,bulkUpdate,bulkDelete,savepoints,queryCTE,jsonQuery,geospatialQuery,streaming,schemaSync, etc.).
@objectstack/driver-sql— Legacy query key fallbacks — Removed support for deprecated query keysfilters(usewhere),sort(useorderBy),skip(useoffset), andtop(uselimit) fromfind,updateMany,deleteMany, andcountmethods. The SQL driver now strictly follows theIDataDriver/QueryASTprotocol. Allas anycasts for legacy key access have been eliminated. Tests updated to use only standardQueryASTkeys.
DriverInterface— UseIDataDriverfrom@objectstack/spec/contractsinstead.DriverInterfaceremains as a type alias in both@objectstack/spec/contractsand@objectstack/corefor backward compatibility.
@objectstack/driver-sqlplugin — Migrated the Knex-based SQL driver from@objectql/driver-sqlintopackages/plugins/driver-sql/. The driver implements the standardDriverInterfacefrom@objectstack/coreand imports types from@objectstack/spec/data. Supports PostgreSQL, MySQL, and SQLite (viabetter-sqlite3). Includes schema sync, introspection, aggregation, window functions, transactions, and full CRUD with both QueryAST and legacy filter format support. All 72 unit tests pass against in-memory SQLite.
- Migrate API layer to Hono + Vercel Node adapter — Replaced the vestigial Next.js-style
api/[...path].tscatch-all with a properapi/index.tsHono entrypoint usinghandle(app)fromhono/vercel. Vercel routes now use a rewrite rule (/api/*→/api) for native Hono routing, eliminating path-normalisation hacks and catch-all bundling pitfalls. Kernel boot remains lazy (cold-start only) viaensureApp()/ensureKernel()in_kernel.ts.
- Service-analytics build error (TS6133) — Removed unused
measurevariable innative-sql-strategy.tsthat caused the DTS build to fail withnoUnusedLocalsenabled, blocking the entire CI build pipeline. - Next.js adapter test failures — Updated 9 metadata API test assertions to match the
current
dispatch(method, path, body, queryParams, context)call signature used by the implementation. Tests were still expecting the olddispatch(subPath, context, method, body)signature. - Auth plugin test failures — Fixed 2 tests in
auth-plugin.test.tsthat referenced the wrongAuthManagerinstance viaregisterService.mock.calls. AddedmockClear()before local plugin init to ensuremock.calls[0]points to the correct AuthManager for the test's plugin instance. - SvelteKit adapter test failures — Updated test mock to include
dispatch()method and aligned Metadata, Data, Error handling, and toResponse test assertions with the unified catch-all dispatch pattern used by the implementation and all other adapters (e.g. Hono). Removed obsoletehandleMetadata/handleDatareferences from the mock. - Vercel serverless 404 fix — The previous
api/[...path].tspath-normalisation fix is now superseded by the Hono adapter migration above. The newapi/index.tsentrypoint combined with Vercel rewrites (/api/*→/api) eliminates the routing ambiguity that caused 404s. - Kernel cold-start race condition —
api/_kernel.tsuses a shared boot promise so that concurrent cold-start requests wait for the same initialisation rather than launching duplicate boot sequences. Seed-data failures are treated as non-fatal, and the broker shim is validated after bootstrap with automatic reattachment if lost. - Broker-resilient metadata handler —
HttpDispatcher.handleMetadata()no longer requires a broker upfront. It tries the protocol service and ObjectQL registry first, falling back to the broker only when available. Serverless/lightweight setups without a full message broker now return proper metadata responses instead of throwing 500 errors.
@objectstack/service-analytics— New multi-driver analytics service implementingIAnalyticsService. Uses a Strategy Pattern with priority-ordered chain: P1 NativeSQLStrategy (pushes queries as native SQL to Postgres/MySQL drivers), P2 ObjectQLStrategy (translates to ObjectQLaggregate()AST), P3 InMemoryStrategy (delegates to existingMemoryAnalyticsServicefor dev/test). IncludesCubeRegistryfor auto-discovery of cubes from manifest definitions and object schema inference,AnalyticsServicePluginfor kernel plugin lifecycle,generateSql()dry-run capability, andqueryCapabilities()driver probing for dynamic strategy selection. 34 unit tests covering all strategy branches.- Studio system objects visibility — Studio now auto-registers all system objects (sys_user,
sys_role, sys_audit_log, etc.) from plugin-auth, plugin-security, and plugin-audit at kernel
initialization. The sidebar "System" group dynamically lists all
isSystem=trueobjects with a collapsible "System Objects" section. A filter toggle on the Data group allows showing/hiding system objects from the main object list. - ObjectSchema
namespaceproperty — New optionalnamespacefield onObjectSchemafor logical domain classification (e.g.,'sys','crm'). When set,tableNameis auto-derived as{namespace}_{name}byObjectSchema.create()unless an explicittableNameis provided. This decouples the logical object name from the physical table name and enables unified routing, permissions, and discovery by domain. - SystemObjectName constants — Extended with all system objects:
ORGANIZATION,MEMBER,INVITATION,TEAM,TEAM_MEMBER,API_KEY,TWO_FACTOR,ROLE,PERMISSION_SET,AUDIT_LOG(in addition to existingUSER,SESSION,ACCOUNT,VERIFICATION,METADATA). - plugin-auth system objects — Added
SysOrganization,SysMember,SysInvitation,SysTeam,SysTeamMember,SysApiKey,SysTwoFactorobject definitions withnamespace: 'sys'. Existing objects (SysUser,SysSession,SysAccount,SysVerification) migrated to use namespace convention. - plugin-security system objects — Added
SysRoleandSysPermissionSetobject definitions. - plugin-audit — New plugin package with
SysAuditLogimmutable audit trail object definition. - StorageNameMapping.resolveTableName() — Now supports namespace-aware auto-derivation
(
{namespace}_{name}fallback when no explicittableNameis set).
- ObjectFilterSchema
includeSystemdefault — Changed fromfalsetotrue. Studio ObjectManager now includes system objects by default. Users can toggle visibility via the Data group filter control. - System object naming convention — All system objects now use
namespace: 'sys'with shortname(e.g.,name: 'user'instead ofname: 'sys_user'). Thesys_prefix is auto-derived viatableName={namespace}_{name}. File naming followssys-{name}.object.tspattern. - plugin-auth object exports — New canonical exports use
Sys*prefix (e.g.,SysUser,SysSession). LegacyAuth*exports are preserved as deprecated re-exports for backward compatibility. - sys_metadata object — Migrated to
namespace: 'sys',name: 'metadata'convention (tableName auto-derived assys_metadata). - Locale code fallback — New
resolveLocale()helper in@objectstack/corethat resolves locale codes through a 4-step fallback chain: exact match → case-insensitive match (zh-cn→zh-CN) → base language match (zh-CN→zh) → variant expansion (zh→zh-CN). Used bycreateMemoryI18n,HttpDispatcher.handleI18n(), andI18nServicePluginroute handlers. - Auto-detection of I18nServicePlugin — Both
DevPluginand CLIservecommand now automatically detecttranslations/i18nconfig in the stack definition and registerI18nServicePluginfrom@objectstack/service-i18nwhen available. Falls back to the core in-memory i18n (with locale resolution) if the package is not installed. - Enhanced i18n diagnostics —
AppPluginnow emits clear warnings when:- Translations exist but no i18n service is registered (guides user to add the plugin).
- Translations are loaded into a fallback/stub i18n service (recommends production plugin).
- i18n locale fallback in REST routes —
HttpDispatcher.handleI18n()translations and labels endpoints now resolve locale codes via fallback when exact match returns empty translations. The response includesrequestedLocalewhen a fallback was used.
- DevPlugin i18n stub — Replaced the duplicate
createI18nStub()inDevPluginwithcreateMemoryI18nfrom@objectstack/core, ensuring locale fallback works consistently in dev mode. DevPlugin now triesI18nServicePluginbefore the stub when stack has translations. createMemoryI18nnow usesresolveLocale()internally fort()andgetTranslations(), enabling locale fallback (e.g.zh→zh-CN) without any plugin changes.- CLI
servecommand now auto-registersI18nServicePluginwhen config has translations/i18n, mirroring DevPlugin's auto-detection behavior for production environments.
- i18n route self-registration — Moved i18n REST endpoint registration from
RestServertoI18nServicePlugin(and kernel fallback). The i18n plugin now self-registers/api/v1/i18n/*routes via thekernel:readyhook, following the same autonomous plugin pattern used byAuthPlugin,WorkflowPlugin, and other service plugins.RestServerno longer registers or manages any i18n endpoints, keeping it strictly a protocol-driven gateway. - Removed
enableI18nflag fromRestApiConfigschema (rest-server.zod.ts) — i18n endpoints are now controlled by the i18n service plugin's ownregisterRoutesoption (default:true). - Removed
registerI18nEndpoints()method fromRestServerclass. I18nServicePluginnow acceptsregisterRoutesandbasePathoptions for HTTP route control.- i18n endpoints now work independently of
RestServer, enabling MSW/mock test environments to serve i18n routes without any REST API gateway dependency. - Dispatcher i18n bridge routes —
createDispatcherPlugin()now registers i18n HTTP route bridges (GET /i18n/locales,GET /i18n/translations/:locale,GET /i18n/labels/:object/:locale) viaHttpDispatcher.handleI18n(), ensuring i18n endpoints work even when only the kernel's memory fallback i18n is active (no explicitI18nServicePluginloaded). This is consistent with how auth, analytics, packages, storage, and automation services are bridged.
- i18n as core built-in service — The i18n service is now a
corecriticality service with automatic in-memory fallback. When no plugin (e.g.I18nServicePlugin) registers an i18n service, the kernel auto-injectscreateMemoryI18n(in-memory Map-backed II18nService implementation) duringvalidateSystemRequirements(). This ensures/api/v1/i18n/*routes and discovery always report i18n as available, even withoutplugin-i18ninstalled. createMemoryI18nfallback factory in@objectstack/core(packages/core/src/fallbacks/memory-i18n.ts) implementingII18nServicecontract with translation loading, dot-notation key resolution, parameter interpolation, and locale management.
ServiceRequirementDef.i18nupgraded from'optional'to'core'— kernel now warns (instead of silently ignoring) when no i18n service is registered, and auto-injects in-memory fallback.SERVICE_CONFIG['i18n'].plugininprotocol.tscorrected from'plugin-i18n'to'service-i18n'to match the actual@objectstack/service-i18npackage name.- Updated kernel-services.mdx documentation to reflect i18n as core/built-in capability.
- AppPlugin getService crash on missing services —
AppPlugin.start()andloadTranslations()now wrapctx.getService()in try/catch, since the kernel'sgetServicethrows when a service is not registered (rather than returningundefined). This was the direct cause ofplugin.app.com.example.crm failed to start— the i18n service was not registered, sogetService('i18n')threw an unhandled exception. - CLI serve: host config AppPlugin mis-wrap —
serve.tsno longer wraps a host/aggregator config (one that already contains instantiated plugins in itspluginsarray) with an extraAppPlugin. This prevents theplugin.app.dev-workspace failed to starterror and eliminates duplicate plugin registration when runningpnpm dev. - plugin-auth CJS→ESM interop — Added
moduleandexportsfields to@objectstack/plugin-authpackage.json so Node.js resolves the ESM build (.mjs) when using dynamicimport(), eliminating theExperimentalWarning: CommonJS module … is loading ES Modulewarning caused bybetter-authbeing ESM-only. - i18n service registration & state inconsistency — Discovery API (
getDiscoveryInfo) now uses the same asyncresolveService()fallback chain that request handlers (handleI18n) use, ensuring the reported service status is always consistent with actual runtime availability. - Discovery
localefield is now populated from the actual i18n service (getDefaultLocale,getLocales) instead of being hardcoded, so clients get accurate locale information. - Updated all framework adapters (Hono, Express, Fastify, Next.js, NestJS, Nuxt, SvelteKit),
the dispatcher plugin, and the MSW plugin to
awaitthe now-asyncgetDiscoveryInfo().
- AppPlugin i18n auto-loading —
AppPluginnow automatically loads translation bundles from app configs (translationsarray) into the kernel's i18n service during thestartphase, coordinating i18n data loading across server/dev/mock environments. - i18n service registration guide in
content/docs/guides/kernel-services.mdxdocumenting service registration patterns, discovery consistency, and AppPlugin auto-loading behavior.
- Updated ROADMAP.md for v3.0 release preparation with full codebase scan results
- Audited all @deprecated items: 14 in spec, 9 in runtime packages (23 total)
- Identified stale deprecation notices targeting v2.0.0 (current: v2.0.7)
- Updated metrics: 172 schema files, 191 test files, 5,165 tests, 7,095 .describe() annotations
- The following items are scheduled for removal in v3.0.0 (see
packages/spec/V3_MIGRATION_GUIDE.md):Hub.*barrel re-exports fromhub/index.tslocation(singular) onActionSchema— uselocations(array)definePlugin()in spec — will move to@objectstack/corecreateErrorResponse()/getHttpStatusForCategory()in spec — will move to@objectstack/coreRateLimitSchema,RealtimePresenceStatus,RealtimeActionaliases- Event bus helper functions (
createDefaultEventBusConfig,createDefaultDLQConfig,createDefaultEventHandlerConfig) HttpDispatcherclass in@objectstack/runtimecreateHonoApp()in@objectstack/hono
2.0.7 - 2026-02-11
- Modularized
kernel/events.zod.ts(765 lines) into 6 focused sub-modules for better tree-shaking:events/core.zod.ts: Priority, metadata, type definition, base eventevents/handlers.zod.ts: Event handlers, routes, persistenceevents/queue.zod.ts: Queue config, replay, sourcingevents/dlq.zod.ts: Dead letter queue, event log entriesevents/integrations.zod.ts: Webhooks, message queues, notificationsevents/bus.zod.ts: Complete event bus config and helpers
- Created v3.0 migration guide (
packages/spec/V3_MIGRATION_GUIDE.md)
kernel/events.zod.tsnow re-exports from sub-modules (backward compatible)- Updated all packages to version 2.0.7 with unified versioning
2.0.6 - 2026-02-11
- Patch release for maintenance and stability improvements
- Updated all packages to version 2.0.6 with unified versioning
2.0.5 - 2026-02-10
- Unified all package versions to 2.0.5
- Added
@objectstack/plugin-authand@objectstack/plugin-securityto the changeset fixed versioning group - All packages now release together under the same version number
2.0.4 - 2026-02-10
- Patch release for maintenance and stability improvements
- Updated all packages to version 2.0.4 with unified versioning
2.0.3 - 2026-02-10
- Patch release for maintenance and stability improvements
- Updated all packages to version 2.0.3 with unified versioning
2.0.2 - 2026-02-10
- Exclude generated JSON schema files from git tracking
- Add
packages/spec/json-schema/to.gitignore(1277 generated files, 5MB) - JSON schema files are still generated during
pnpm buildand included in npm publish - Fix studio module resolution logic for better compatibility
- Updated all packages to version 2.0.2 with unified versioning
2.0.1 - 2026-02-09
- Patch release for maintenance and stability improvements
- Updated all packages to version 2.0.1 with unified versioning
0.9.1 - 2026-02-03
- Patch release for maintenance and stability improvements
- Updated all packages to version 0.9.1 with unified versioning
0.9.0 - 2026-02-03
- Minor version bump for new features and improvements
- All packages updated to version 0.9.0
0.8.2 - 2026-02-02
- BREAKING: Removed
view-storage.zod.tsandViewStoragerelated types from@objectstack/spec - BREAKING: Removed
createView,updateView,deleteView,listViewsfromObjectStackProtocolinterface - BREAKING: Removed in-memory View Storage implementation from
@objectstack/objectql - Updated
@objectstack/plugin-mswto dynamically load@objectstack/objectqlto avoid hard dependencies
0.8.1 - 2026-02-01
- Patch release for maintenance and stability improvements
- Updated all packages to version 0.8.1
0.8.0 - 2026-02-01
- Upgrade to Zod v4 and protocol improvements
- Aligned all protocol definitions with stricter type safety
- Updated all packages to version 0.8.0
0.7.2 - 2026-01-31
- Updated system protocol JSON schemas (events, worker, metadata-loader)
- Enhanced documentation structure for system protocols
- Generated comprehensive JSON schema documentation
0.7.1 - 2026-01-31
- Patch release for maintenance and stability improvements
- Updated all packages to version 0.7.1
0.6.1 - 2026-01-28
- Patch release for maintenance and stability improvements
- Updated all packages to version 0.6.1
0.4.1 - 2026-01-27
- Synchronized plugin-msw version to 0.4.1 (was incorrectly at 0.3.3)
- Updated runtime peer dependency versions to ^0.4.1 across all plugins
- Fixed internal dependency version mismatches
0.4.0 - 2026-01-26
- Updated all core packages to version 0.4.0
0.3.3 - 2026-01-25
- Enhanced GitHub workflows for CI, release, and PR automation
- Added comprehensive prompt templates for different protocol areas
- Improved project documentation and automation guides
- Updated changeset configuration
- Added cursor rules for better development experience
- Updated all packages to version 0.3.3
0.3.2 - 2026-01-24
- Patch release for maintenance and stability improvements
- Updated all packages to version 0.3.2
0.3.1 - 2026-01-23
- Organized zod schema files by folder structure
- Improved project documentation
0.3.0 - 2026-01-22
- Comprehensive documentation structure with CONTRIBUTING.md
- Documentation hub at docs/README.md
- Standards documentation (naming-conventions, api-design, error-handling)
- Architecture deep dives (data-layer, ui-layer, system-layer)
- Code of Conduct
- Changelog template
- Migration guides structure
- Security and performance guides
- Updated README.md with improved documentation navigation
- Enhanced documentation organization following industry best practices
- All packages now use unified versioning (all packages released together with same version number)
0.1.1 - 2026-01-20
- Initial protocol specifications
- Zod schemas for data, UI, system, AI, and API protocols
- JSON schema generation
- Basic documentation site with Fumadocs
- Example implementations (CRM, Todo)
## [X.Y.Z] - YYYY-MM-DD
### Added
- New features or capabilities
### Changed
- Changes to existing functionality
### Deprecated
- Features that will be removed in upcoming releases
### Removed
- Features that have been removed
### Fixed
- Bug fixes
### Security
- Security-related changesWhen making changes:
- Add entries under
[Unreleased]section - Choose the appropriate category: Added, Changed, Deprecated, Removed, Fixed, Security
- Write clear, concise descriptions of your changes
- Link to PRs or issues where applicable:
- Feature description (#PR_NUMBER)
Example:
### Added
- New encrypted field type for sensitive data (#123)
- Support for PostgreSQL window functions in query protocol (#124)
### Fixed
- Validation error when using lookup fields with filters (#125)When releasing a new version:
- Create a new version section from the
[Unreleased]content - Move entries from
[Unreleased]to the new version section - Add release date in YYYY-MM-DD format
- Tag the release in git:
git tag -a v0.2.0 -m "Release v0.2.0" - Update links at the bottom of the file
Following Semantic Versioning:
- MAJOR version (X.0.0): Incompatible API changes
- MINOR version (0.X.0): Add functionality in a backward compatible manner
- PATCH version (0.0.X): Backward compatible bug fixes
- Added: New features, protocols, schemas, or capabilities
- Changed: Changes to existing functionality
- Deprecated: Features marked for removal (but still working)
- Removed: Features that have been removed
- Fixed: Bug fixes
- Security: Security vulnerability fixes or improvements
Mark breaking changes clearly:
### Changed
- **BREAKING**: Renamed `maxLength` to `maxLen` in FieldSchema (#126)
Migration: Update all field definitions to use `maxLen` instead of `maxLength`- Update CHANGELOG.md with release notes
- Update version in package.json files
- Run
pnpm changeset versionto update package versions - Commit changes:
git commit -m "chore: release vX.Y.Z" - Create git tag:
git tag -a vX.Y.Z -m "Release vX.Y.Z" - Push:
git push && git push --tags - Run
pnpm releaseto publish packages