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.
os auth login/register/menow work against multi-project servers —@objectstack/clientwas sending requests to better-auth's/sign-in/email,/sign-up/email,/sign-out,/get-sessionwithout anOriginheader, which better-auth rejected withMISSING_OR_NULL_ORIGIN: Missing or null Originagainst the defaulttrustedOrigins: ['http://localhost:*']. Auth methods now sendOrigin: <baseUrl>automatically. Additionally, thelogin()andregister()response normalizer now accepts both the wrapped{ data: { token, user } }shape and better-auth's flat{ token, user }shape so the CLI'sauth loginflow stores the token correctly.os projects bind+os projects create --artifactCLI commands — Third-party developers can now bind a locally-compiled bundle to a multi-project server without rawcurl.os projects create --org <id> --name <name> --artifact ./dist/objectstack.jsonprovisions a new project and seeds the bundle in one call (also supports--template <id>for the parity with built-in templates). The newos projects bind <projectId> --artifact <path>updates an existing project'smetadata.artifact_path, with--buildto runobjectstack compilefirst and--reseedas a placeholder for the future server-side reseed endpoint. Both flags resolve relative paths to absolute and validate the file exists before issuing the API call. Verified end-to-end: project created via CLI,/api/v1/projects/{id}/data/accountreturns the seeded CRM accounts.- Third-party project binding via
metadata.artifact_path— Multi-projectPOST /api/v1/cloud/projectsnow acceptsmetadata.artifact_pathto bind a locally-compiled bundle (e.g.examples/app-crm/dist/objectstack.json) into a fresh project. Provisioning loads the JSON, registers schemas in the per-project ObjectQL engine, and seeds the bundle'sdataarrays — same pipeline that built-in templates use. NewTemplateSeeder.seedBundle({ projectId, bundle })method exposes the seeder for arbitrary bundles. Bind errors (read failure, malformed JSON) are recorded as non-fatalmetadata.artifactBindErrorso the project still flips toactive. Verified end-to-end: query/api/v1/projects/{id}/data/accountreturns the seeded CRM accounts. AppBundleResolverfor live kernel binding —apps/servernow shipscreateFsAppBundleResolver()inapps/server/server/fs-app-bundle-resolver.ts. Readssys_project.metadata.artifact_path(orartifact_paths[]) at per-project kernel boot, with optionalOBJECTSTACK_PROJECT_ARTIFACTS=projId:path,…env override andOBJECTSTACK_PROJECT_ARTIFACT_ROOTfor relative path resolution. Used wherever a project kernel is materialized (trigger / function / metadata API requests). Replaces the previousreturn []stub.
apps/server:GET /api/v1/cloud/templatesnow returns the full template registry (blank,crm,todo) on Vercel / play.objectstack.ai. Root cause: the dispatcher resolved templates through atemplate-seederservice registered byMultiProjectPlugin, and on Vercel cold starts that service registration could be missed by the request handler — the dispatcher then silently returned{ templates: [], total: 0 }. Added acreateTemplatesRoutePluginthat registers/cloud/templatesdirectly onhttp.serverfrom a static, module-scopelistTemplates()snapshot, registered beforeDispatcherPlugin. Local single-project mode is unchanged.packages/runtime/http-dispatcher.ts:/cloud/templatesfallback now logs the resolution error viaconsole.errorinstead of swallowing it silently, so the underlying cause is visible in production logs.apps/server/objectstack.config.ts:multiProjectPluginProxy.initnow wraps the inner init in try/catch and logs failures, preventing one-off init errors from silently leaving the kernel withouttemplate-seeder/kernel-manager.apps/server: Multi-project / cloud mode now also servesGET /api/v1/studio/runtime-config(returns{ singleProject: false }) via a newcreateStudioRuntimeConfigPlugin. Eliminates the 404 the Studio SPA logged on first load whenOBJECTSTACK_MULTI_PROJECT=true(the default for rootpnpm dev). Single-project mode is unchanged.
- M1 — Project Artifact envelope schema (
@objectstack/spec) — Introduced the v0ProjectArtifactSchemainpackages/spec/src/system/project-artifact.zod.ts, the immutable envelope thatobjectstack compilewill produce and ObjectOS will consume at boot. Required fields:schemaVersion(literal'0.1'),projectId,commitId,checksum({ algorithm, value }),metadata(per-category arrays,passthrough()for forward compatibility),functions(inlined source with optional language/source/hash), andmanifest(plugin / driver / engine requirements). OptionalbuiltAt,builtWith, and a reservedpayloadRef({ url, expiresAt, checksum }) for future S3 indirection without an envelope bump. 14 new tests inproject-artifact.test.ts. Resolves ROADMAP M1; unblocks M3 (Artifact API) and M4 (ObjectOS artifact loader).
- D1 — ObjectOS metadata DB bridge removed —
MetadataPluginno longer registerssys_metadata/sys_metadata_historyinto the ObjectOS manifest and no longer auto-bridges ObjectQL toDatabaseLoaderduringstart(). Runtime metadata is now file/artifact backed; database-backed metadata persistence remains an explicitMetadataManagercapability for control-plane services. Updated ROADMAP, North Star, Metadata Service docs, and ObjectStack skills to reflect the boundary. - D5 —
ManifestSchema.scopeenum trimmed to'cloud' | 'system' | 'project'— Removed the deprecated'platform'and'environment'aliases frompackages/spec/src/kernel/manifest.zod.ts. No call site in the workspace was setting the deprecated values, so this is a clean break. Resolves ROADMAP D5. - D4 —
ObjectSchemaBase.namespaceremoved — Object identity is now single-sourced onname. The deprecatednamespacefield has been removed fromObjectSchemaBase(packages/spec/src/data/object.zod.ts); legacy inputs that still setnamespaceare silently stripped by Zod's default object behavior. Package-level namespace (FQN computation, marketplace publishing,DatasourceRoutingRule.namespace) is intentionally retained as an internal mechanic. Five legacyObjectSchema namespacetest blocks were rewritten as a singlename-as-identityblock. Resolves ROADMAP D4. - D7 — Plugin manifest header + objects unified per package — Each plugin / service now exposes a single canonical
src/manifest.tsfile that bothobjectstack.config.ts(compile-time) and the runtime*-plugin.ts(manifest.register()) import from. This eliminates a real divergence inplugin-authandplugin-securitywhose configs imported from a non-existent./src/objects/directory and silently shipped empty object lists at compile time while their runtime registrations were intact. Affected packages:@objectstack/plugin-auth,@objectstack/plugin-security,@objectstack/service-tenant. Resolves ROADMAP D7.
-
@objectstack/cli— Studio static plugin no longer breaks after a Studio rebuild —createStudioStaticPlugin()inpackages/cli/src/utils/studio.tshad two latent bugs that caused the browser to fail withFailed to load module script: Expected a JavaScript-or-Wasm module script but the server responded with a MIME type of "text/html"whenever Studio's bundle hash changed between server start and the request:index.htmlwas read once at startup and held in memory; a Studio rebuild produced new hashed asset filenames but the cached HTML still referenced the old hashes.- The SPA fallback served
index.htmlfor every unmatched path under/_studio/, including/_studio/assets/*. Combined with (1), missing hashed assets would silently respond with HTML — producing the strict-MIME error in the browser. Fix: readindex.htmlfresh on each fallback request, and return real 404 for/_studio/assets/*misses so the rebuild/redeploy mismatch surfaces immediately instead of being masked. Verified end-to-end againstlocalhost:3000/_studio/after a Studio rebuild.
-
@objectstack/service-tenant— system objects now actually register —createTenantPlugin()previously declared its control-plane schemas (sys_project,sys_project_credential,sys_project_member,sys_package,sys_package_version,sys_package_installation,sys_tenant_database) via a top-levelobjects: [...]field on the kernel plugin object. The kernel only consumesplugin.objectsfor nested plugins inside a parent manifest (packages/objectql/src/engine.ts→registerPlugin()), so plugins added viakernel.use(plugin)had to use themanifestservice (asAuthPlugin/SecurityPlugin/SetupPluginalready do). The result was thatsys__projectetc. were never registered withSchemaRegistry, soObjectQL.getDriver('sys__project')could not match thenamespace: 'sys' → tursodatasourceMappingrule (the lookup returnedundefinedand skipped past the namespace check), silently routing every control-plane write to the default driver — typically the in-memory driver. On Vercel each lambda instance has its own memory, soPOST /api/v1/cloud/projects"succeeded" with HTTP 202 but the row evaporated on cold start, causing the subsequentGET /api/v1/cloud/projects/:idto return 404 even though the user/organization writes (registered through the proper path byAuthPlugin) were correctly persisted in Turso. The plugin now registers the same set of objects viactx.getService('manifest').register({ id: 'com.objectstack.tenant', namespace: 'sys', objects: [...] })and throws if the manifest service is unavailable, fail-fast instead of silent data loss. Also affected: package install/upgrade endpoints, project credential rotation, project membership reads.
- Platform object definitions consolidated in
@objectstack/platform-objects— Removed the now-redundant@objectstack/objectospackage. Metadata-layer objects (SysObject,SysView,SysAgent,SysTool,SysFlow) are registered directly from@objectstack/platform-objects/metadata, and plugin/service packages no longer re-export platform objects through compatibilityobjectsfacades. examples/app-crm— showcasefieldGroupsMVP — The CRM reference example (Account,Contact,Opportunity,Lead) now demonstrates the newfieldGroupsprotocol end to end. Each object declares logical groups (e.g., Basic Information, Financials, Contact Information, Ownership & Status, System) and every field opts in viagroup: '<key>'. No business logic changed — only field-layout metadata — so existing validations, workflows, indexes, and state machines are unaffected. Useful as a reference when designing multi-group forms and detail pages.
- Field Groups (
fieldGroups) — simplified MVP protocol — Introduced a data-layer protocol for grouping fields on an object in forms, detail pages, and editors. Designed to be AI-generation- and extension-friendly by intentionally minimizing surface area:- New
ObjectFieldGroupSchemainpackages/spec/src/data/object.zod.tswithkey(snake_case machine key),label, optionalicon,description,defaultExpanded(defaulttrue), andvisibleOn(expression for conditional visibility). Noorderproperty — array declaration order is the display order. ObjectSchemagains an optionalfieldGroups: ObjectFieldGroup[]. Group keys are validated to be unique within an object.- The existing
Field.group: stringproperty onFieldSchemais the sole field→group assignment mechanism. Field → group mapping is derived automatically from metadata registration; in-group display order equals the traversal order ofObjectSchema.fields. Extension packages and runtime code useField.groupuniformly. - Supported migrations at this layer: add / rename / delete / reorder groups (by editing the
fieldGroupsarray) and assigning an existing field to a group (by editingField.group). Explicit per-field in-group ordering is deferred to a future iteration. - New
ObjectFieldGroup/ObjectFieldGroupInputtype exports alongside the schema. - Tests: 12 new round-trip cases in
packages/spec/src/data/object.test.tscovering minimal/full-group parsing, required fields, snake_case key validation, declaration-order preservation, duplicate-key rejection,Field.groupreferencing, andObjectSchema.create()integration.
- New
- Environment-per-database multi-tenancy (
service-tenantv4.1) — Refactored the multi-tenant architecture from "per-organization database" to per-environment database high-isolation, with a hard split between Control Plane (environment registry / addressing / credentials / RBAC) and Data Plane (one physical database per environment). Seedocs/adr/0002-environment-database-isolation.mdfor the full rationale and trade-offs.- Zod protocol schemas (
packages/spec/src/cloud/environment.zod.ts):EnvironmentSchema,EnvironmentDatabaseSchema,DatabaseCredentialSchema,EnvironmentMemberSchema,EnvironmentTypeSchema,EnvironmentStatusSchema,EnvironmentRoleSchema,DatabaseCredentialStatusSchema,ProvisionEnvironmentRequest/ResponseSchema,ProvisionOrganizationRequest/ResponseSchema.TenantDatabaseSchemais now marked@deprecated. - Control-plane objects (
packages/services/service-tenant/src/objects/):sys_environment(UNIQUE(organization_id, slug)),sys_environment_database(UNIQUEenvironment_id— exactly one DB per environment),sys_database_credential(rotatable, encrypted, withactive/rotating/revokedlifecycle),sys_environment_member(UNIQUE(environment_id, user_id), owner / admin / maker / reader / guest). Every field carries.describe()metadata and every uniqueness constraint is explicit. EnvironmentProvisioningService(packages/services/service-tenant/src/environment-provisioning.ts):provisionOrganization()bootstraps a new org with a default environment and DB in one call;provisionEnvironment()allocates any subsequent dev / test / sandbox / preview environment;rotateCredential()mints a newactivecredential and revokes the previous one. PluggableEnvironmentDatabaseAdapter(initialturso;libsql/sqlite/postgresdrop in without core changes) andSecretEncryptorhooks.- Tenant plugin wiring:
createTenantPlugin()now registers the current control-plane objects directly from@objectstack/platform-objects/tenant. - v4 → v5 migration skeleton (
packages/services/service-tenant/migrations/v4-to-v5-env-migration.ts): idempotent, non-destructive, re-encrypts credentials with the current KMS key, reuses existing physical DBs as each org's newprodenvironment DB — no data movement required. - Tests: 22 new schema round-trip tests in
packages/spec/src/cloud/environment.test.ts, 10 new provisioning tests inpackages/services/service-tenant/src/environment-provisioning.test.tscovering organization bootstrap, environment creation, default-environment invariants, adapter routing, credential rotation, and encryption hooks.
- Zod protocol schemas (
- Polished
examples/app-crmdashboards — Rewroteexecutive,sales, andservicedashboards and added a new unifiedcrmoverview dashboard, modeled after the reference implementation at objectstack-ai/objectui/examples/crm. The dashboards now use the framework's first-class metadata fields instead of ad-hoc hex strings stuffed intooptions.color:- Semantic
colorVarianttokens (success/warning/danger/blue/teal/purple/orange) replace raw hex codes - Each widget carries a
description,chartConfig(axes, color palette, annotations, interaction), and a headeractionUrl/actionType/actionIconfor drill-down - Each dashboard declares a structured
headerwith action buttons, adateRangeglobal time filter,globalFilters(owner / industry / priority lookups), and arefreshInterval - KPI metric widgets carry
icon,format, andtrendindicators (direction + delta + label) inoptions, mirroring the objectui reference visual style - Chart variety expanded:
area(revenue trends),donut(lead source / industry),funnel(pipeline by stage),gauge(SLA compliance),horizontal-bar(rep ranking), with proper axis titles and value formatters - Table widgets use structured
columns: [{ header, accessorKey, format }]instead of bare field-name arrays - New
examples/app-crm/test/dashboard.test.tsvalidates every dashboard againstDashboardSchemaand enforces these conventions
- Semantic
- Release-readiness documentation pass (42 packages) — Aligned every
@objectstack/*package for the formal v4.x release:- Canonical README template and
package.jsonpublishing checklist committed atdocs/internal/PACKAGE_README_TEMPLATE.md - New
packages/services/service-package/README.mddocumenting the package registry service - All
package.jsonfiles now carrydescription, at least 3keywords, a fullrepositoryblock withdirectory,homepage,bugs,engines.node,publishConfig.access: public, and afileswhitelist @objectstack/service-tenant(was0.1.0) and@objectstack/service-package(was1.0.0) bumped to4.0.4in lockstep with the release train- Rewrote thin READMEs for
core,rest,driver-memory,plugin-security, and all seven framework adapters (express,fastify,hono,nestjs,nextjs,nuxt,sveltekit) to the canonical structure: overview, installation, quick start, key exports, configuration, when/when-not, related packages, and docs links - Updated
content/docs/guides/packages.mdxandcontent/docs/concepts/packages.mdxto reflect the actual 42 package inventory and to includeservice-packageandservice-tenant
- Canonical README template and
- Studio left metadata list not refreshing on package switch — In
apps/studio/src/routes/$package.tsx, theAppSidebarpackage-switcher'sonSelectPackagehandler only updated localselectedPackagestate. A URL→stateuseEffectin the same layout then immediately reverted that state back to match the unchanged$packageroute param, soAppSidebar.loadMetadata(keyed onselectedPackage) never re-ran and the left metadata tree stayed stuck on the previous package. The dropdown now navigates to/$newPackage, making the URL the single source of truth; the URL→state effect then updatesselectedPackagenormally and the metadata list refreshes for the new package. (apps/studio/src/routes/$package.tsx) - Cross-origin auth tokens stripped in
@objectstack/honoadapter (follow-up to PR #1178) —createHonoApp()was not exposingset-auth-tokenviaAccess-Control-Expose-Headers, diverging fromplugin-hono-server's CORS wiring. On Vercel deployments (where all traffic flows throughcreateHonoApp()), the browser stripped the header from every response, preventing the better-authbearer()plugin from delivering rotated session tokens to cross-origin clients. Cross-origin sessions silently broke even after the wildcard fixes in #1177/#1178. The adapter now always includesset-auth-tokeninexposeHeaders, merged with any user-supplied values, mirroring the invariant established in commit151dd19c. (packages/adapters/hono/src/index.ts) - CORS wildcard patterns in
@objectstack/honoadapter (follow-up to PR #1177) —createHonoApp()was the third CORS code path that still treated wildcard origins (e.g.https://*.objectui.org) as literal strings when passing them to Hono'scors()middleware. Becauseapps/serverroutes all non-OPTIONS requests through this adapter on Vercel, the browser would see a successful preflight (handled by the Vercel short-circuit) followed by a POST/GET response with noAccess-Control-Allow-Originheader, blocking every real request. The adapter now importshasWildcardPattern/createOriginMatcherfrom@objectstack/plugin-hono-serverand uses the same matcher-function branch asplugin-hono-server, so all three Hono-based CORS paths share a single source of truth. (packages/adapters/hono/src/index.ts) - CORS wildcard patterns on Vercel deployments —
CORS_ORIGINvalues containing wildcard patterns (e.g.https://*.objectui.org,https://*.objectstack.ai,http://localhost:*) no longer cause browser CORS errors whenapps/serveris deployed to Vercel. The Vercel entrypoint's OPTIONS preflight short-circuit previously matched origins with a literalArray.includes(), treating*as a plain character and rejecting legitimate subdomains. It now shares the same pattern-matching logic as the Hono plugin'scors()middleware via new exportscreateOriginMatcher/hasWildcardPattern/matchOriginPattern/normalizeOriginPatternsfrom@objectstack/plugin-hono-server. (apps/server/server/index.ts,packages/plugins/plugin-hono-server/src/pattern-matcher.ts)
- Claude Code integration (
CLAUDE.md) — Added rootCLAUDE.mdfile so that Claude Code automatically loads the project's system prompt when launched in the repository. Content is synced with.github/copilot-instructions.mdand includes build/test quick-reference commands, all prime directives, monorepo structure, protocol domains, coding patterns, and domain-specific prompt references. This complements the existing GitHub Copilot instructions andskills/directory. - AI Skills documentation pages — Added two new documentation pages covering the Skills System:
content/docs/concepts/skills.mdx— Conceptual overview of the skills architecture, philosophy, and structurecontent/docs/guides/skills.mdx— Complete reference for all 10 ObjectStack AI skills with usage examples and prompts- Updated top-level navigation to include
conceptssection - Added skills links to homepage cards, guides index, and navigation meta files
- Skills Module Structure Refactor — Refactored all skills in
skills/directory to follow shadcn-ui's fine-grained layering pattern. Each skill now has:- Concise
SKILL.md— High-level overview with decision trees and quick-start examples, referencing detailed rules rules/directory — Detailed implementation rules with incorrect/correct code examples for better AI comprehensionevals/directory — Placeholder for future evaluation tests to validate AI assistant understanding- Skills refactored:
objectstack-schema(formerlyobjectstack-data) — Extracted rules for naming, relationships, validation, indexing, field types, and hooks (moved from objectstack-hooks)objectstack-plugin(formerlyobjectstack-kernel) — Extracted rules for plugin lifecycle, service registry, and hooks/events systemobjectstack-query— NEW skill for filters, sorting, pagination, aggregation, joins, expand, full-text search, window functionsobjectstack-hooks— DEPRECATED and consolidated intoobjectstack-schema/rules/hooks.md(hooks are core to data operations)objectstack-ui,objectstack-api,objectstack-automation,objectstack-ai,objectstack-i18n,objectstack-quickstart— Addedrules/andevals/structure with initial pattern documentation
- Benefits:
- Improved maintainability — Detailed rules are separated from high-level overview
- Better AI comprehension — Incorrect/correct examples make patterns clearer
- Enhanced testability —
evals/directory ready for skill validation tests - Reduced skill overlap — Hooks integrated into data skill where they belong
- Preserved skill independence — Each skill remains independently installable/referenceable (no global routing required)
- Concise
- Studio tests: failing CI on
main— Fixed several long-standing test-suite issues in@objectstack/studiothat broke theTest CoreCI job:- Broken relative paths — Tests in
test/plugins/used../src/...but were two levels deep, causing Vite/Vitest to reportFailed to resolve import "../src/plugins". Corrected to../../src/.... vitest.config.tsmissing required aliases — The dedicatedvitest.config.tsonly declared the@alias whilevite.config.tsdeclared ~25 more (e.g.@objectstack/plugin-auth/objects, node built-in stubs). Tests that transitively importedsrc/mocks/createKernel.tsfailed with"./objects" is not exported ….vitest.config.tsnow mirrors the full alias set used byvite.config.ts.- Removed stale tests against non-existent APIs — Deleted
test/components/AppSidebar.test.tsx,test/components/ObjectDataForm.test.tsx,test/components/ObjectDataTable.test.tsx. These were added as scaffolding against APIs that don't match the current components (wrong prop names, missing TanStack Router context) and never passed in CI. - Rewrote
test/plugins/plugin-system.test.tsxto match the actualPluginRegistryAPI (getPlugins,getViewers,registerAndActivate, etc.) andPluginRegistryProviderasync activation lifecycle.
- Broken relative paths — Tests in
- Studio: Package switcher not filtering object list — Fixed a bug where switching packages in the Studio left sidebar did not change the displayed object list. The root cause was in
ObjectStackProtocolImplementation.getMetaItems(): after filtering items bypackageIdviaSchemaRegistry.listItems(), the code merged in ALL runtime items from MetadataService without respecting thepackageIdfilter, effectively overriding the filtered results. The same issue existed inHttpDispatcher.handleMetadata()where the MetadataService fallback path also ignoredpackageId. Both paths now correctly filter MetadataService items by_packageIdwhen a package scope is requested. - MetadataPlugin driver bridging fallback — Fixed
MetadataPlugin.start()so the driver service scan fallback (driver.*) is reached when ObjectQL returnsnull(not just when it throws). Previously,setDatabaseDriverwas never called in environments where ObjectQL was not loaded. - Auth trustedOrigins test alignment — Updated
plugin-authtests to match the auto-defaulthttp://localhost:*behavior added in PR #1152 for better-auth CORS support. When notrustedOriginsare configured, the implementation correctly defaults to trusting all localhost ports for development convenience. - Docs build: lucide-react module resolution — Added Turbopack
resolveAliasinapps/docs/next.config.mjsso MDX content files incontent/docs/(outside the app directory) can resolvelucide-react. Turbopack starts module resolution from the file's directory, which doesn't have access to the app'snode_modules/. - Client Hono integration test timeout — Fixed
afterAllhook timeout inclient.hono.test.tsby racingkernel.shutdown()against a 10s deadline. The shutdown can hang when pino's worker-thread flush callback never fires in CI, so the race ensures the hook completes within the 30s vitest limit. - CI: Replace
pnpm/action-setup@v6with corepack — Switched all GitHub Actions workflows (ci.yml,lint.yml,release.yml,validate-deps.yml,pr-automation.yml) frompnpm/action-setup@v6tocorepack enableto fix persistentERR_PNPM_BROKEN_LOCKFILEerrors. Corepack reads the exactpackageManagerfield frompackage.json(including SHA verification), ensuring the correct pnpm version is used in CI. Also bumped pnpm store cache keys to v3 and added a pnpm version verification step. - Broken pnpm lockfile — Regenerated
pnpm-lock.yamlfrom scratch to fixERR_PNPM_BROKEN_LOCKFILE("expected a single document in the stream, but found more") that was causing all CI jobs to fail. The previous merge of PR #1117 only included workflow cache key changes but did not carry over the regenerated lockfile. - service-ai: Fix navigation item labels using deprecated i18n object format — Replaced
{ key, defaultValue }i18n objects with plain string labels inAIServicePlugin's Setup App navigation contributions, completing theI18nLabelSchemamigration from #1054.
- MCP Runtime Server Plugin (
plugin-mcp-server) — New kernel plugin that exposes ObjectStack as a Model Context Protocol (MCP) server for external AI clients (Claude Desktop, Cursor, VS Code Copilot, etc.). Features include:- Tool Bridge: All registered AI tools from
ToolRegistry(9 built-in tools:list_objects,describe_object,query_records,get_record,aggregate_data,create_object,add_field,modify_field,delete_field) are automatically exposed as MCP tools with correct annotations (readOnlyHint, destructiveHint). - Resource Bridge: Object schemas (
objectstack://objects/{objectName}), object list (objectstack://objects), record access (objectstack://objects/{objectName}/records/{recordId}), and metadata types (objectstack://metadata/types) exposed as MCP resources. - Prompt Bridge: Registered agents (
data_chat,metadata_assistant, etc.) exposed as MCP prompts with context arguments (objectName, recordId, viewName). - Transport: stdio transport via
@modelcontextprotocol/sdkfor local AI client integration. - Environment Configuration:
MCP_SERVER_ENABLED=trueto auto-start,MCP_SERVER_NAMEandMCP_SERVER_TRANSPORTfor customization. - Extensibility:
mcp:readykernel hook allows other plugins to extend the MCP server. - Studio frontend AI interface remains unchanged — it continues to use REST/SSE via Vercel Data Stream Protocol.
- Tool Bridge: All registered AI tools from
- Unified
list_objects/describe_objecttools (service-ai) — Merged the duplicatelist_metadata_objects→list_objectsanddescribe_metadata_object→describe_objecttool pairs. Bothdata_chatandmetadata_assistantagents now share the same unified tools with fullfilter,includeFields, snake_case validation, andenableFeaturessupport.DATA_TOOL_DEFINITIONSis reduced from 5 to 3 (query-only tools), whileMETADATA_TOOL_DEFINITIONSretains all 6 tools under the unified names. The duplicateObjectDef/FieldDeftype definitions indata-tools.tsare removed.
- MetadataPlugin: Driver bridging for database-backed persistence —
MetadataPlugin.start()now discovers registered driver services (driver.*) from the kernel service registry and callsmanager.setDatabaseDriver()to enableDatabaseLoader. Previously, no code bridged the kernel's database driver to theMetadataManager, leavingDatabaseLoaderunconfigured and metadata persistence limited to the filesystem only. - MetadataManager: register() no longer writes to FilesystemLoader —
register()now persists metadata only todatasource:protocol loaders (i.e.DatabaseLoader), skippingfile:protocol loaders (FilesystemLoader). Previously,register()broadcast writes to all loaders indiscriminately, causing crashes in read-only environments (e.g. serverless, containerized deployments) whenFilesystemLoader.save()attempted to write to disk. The same protocol filter is applied tounregister()for consistency. - Agent Chat: Vercel SSE Data Stream support — The agent chat endpoint
(
/api/v1/ai/agents/:agentName/chat) now returns Vercel AI SDK v6 UI Message Stream Protocol (SSE) by default, matching the general chat endpoint behaviour. Previously, the agent chat route only returned plain JSON, causingDefaultChatTransport(used by@ai-sdk/reactuseChat) to fail silently — the API responded correctly but the Studio AI Chat Panel rendered no content. The endpoint now usesstreamChatWithTools+encodeVercelDataStreamforstream !== falserequests (the default), and falls back to JSON only whenstream: falseis explicitly set. Studio's error UI is also enhanced to surface SSE parse failures clearly instead of silent failure. - Agent Chat: Vercel AI SDK v6
partsformat support — The agent chat endpoint (/api/v1/ai/agents/:agentName/chat) now accepts Vercel AI SDK v6parts-based message format in addition to the legacycontentstring format. Previously, sending messages withparts(asuseChatv6 does by default) resulted in a 400 error:"message.content must be a string". Shared validation and normalization utilities (validateMessageContent,normalizeMessage) are extracted intomessage-utils.tsfor reuse across both the general chat and agent chat routes. - Studio: Code tab now shows CodeExporter — The Code tab in Studio metadata detail pages
now correctly renders the
CodeExportercomponent (TypeScript/JSON export with copy-to-clipboard) instead of always showing the JSON Inspector preview. The default plugin now registers two separate viewers:json-inspectorfor preview mode andcode-exporterfor code mode. - CI Test Failures — Resolved test failures across multiple packages:
@objectstack/service-ai: Fixed SDK fallback test by mocking@ai-sdk/openaidynamic import (SDK now available as transitive workspace dependency)@objectstack/nuxt,@objectstack/nextjs,@objectstack/fastify,@objectstack/sveltekit: Added missingprefixargument todispatch()assertion calls in adapter tests@objectstack/plugin-auth: Updateddependenciesassertion and addedmanifestservice mock to match current plugin implementation
-
AIServicePlugin Auto-Detection — AIServicePlugin now automatically detects and initializes LLM providers based on environment variables, eliminating the need for manual adapter configuration in each deployment:
- Auto-detection priority:
AI_GATEWAY_MODEL→OPENAI_API_KEY→ANTHROPIC_API_KEY→GOOGLE_GENERATIVE_AI_API_KEY - Graceful fallback to MemoryLLMAdapter when no provider is configured
- Comprehensive logging of selected provider and warnings for missing SDKs
- Supports custom model selection via
AI_MODELenvironment variable - Consistent behavior across CLI, Vercel, Docker, and custom deployments
- Dynamic import failures are handled as soft errors with automatic fallback (#1067)
- Auto-detection priority:
-
Metadata Versioning & History — Comprehensive version history tracking and rollback capabilities for metadata items. Key features include:
MetadataHistoryRecordSchemadefining structure for historical snapshotssys_metadata_historysystem table for version storage- Automatic history tracking in
DatabaseLoaderwith SHA-256 checksum deduplication getHistory(),rollback(), anddiff()methods inIMetadataService- REST API endpoints:
GET /history,POST /rollback,GET /diff HistoryCleanupManagerwith configurable retention policies (age-based and count-based)- Comprehensive test suite covering all history operations
This aligns ObjectStack with enterprise platforms like Salesforce Setup Audit Trail and ServiceNow Update Sets. See
docs/METADATA_HISTORY.mdfor detailed usage. -
CLI: Remote API Commands - Added 12 new CLI commands for interacting with remote ObjectStack servers:
- Authentication:
os auth login,os auth logout,os auth whoami - Data API:
os data query,os data get,os data create,os data update,os data delete - Metadata API:
os meta list,os meta get,os meta register,os meta delete - All commands support
--urland--tokenflags, or use stored credentials from~/.objectstack/credentials.json - Multiple output formats:
--format json|table|yaml(yaml available on all commands) - Environment variable support:
OBJECTSTACK_URL,OBJECTSTACK_TOKEN - See REMOTE_API_COMMANDS.md for full documentation
- Authentication:
-
i18n:
I18nLabelSchemanow acceptsstringonly —label,description,title, and other display-text fields across all UI schemas (AppSchema,NavigationArea,PageSchema,DashboardWidgetSchema,ReportSchema,ChartSchema,NotificationSchema,AriaPropsSchema, etc.) now accept only plain strings. The previousstring | I18nObjectunion type has been replaced withz.string(). i18n translation keys will be auto-generated by the framework at registration time; developers only need to provide the default-language string value. Translations are managed through translation files, not inline i18n objects. (#1054)Migration: Replace any
label: { key: '...', defaultValue: 'X' }withlabel: 'X'. Existing plain-string labels require no changes.Affected plugins updated:
@objectstack/plugin-setup—setup-app.ts,setup-areas.ts@objectstack/plugin-auth— navigation item labels@objectstack/plugin-security— navigation item labels@objectstack/plugin-audit— navigation item labels
- README rewrite — Rewrote
README.mdto accurately reflect theobjectstack-ai/frameworkrepository. Updates include: corrected title ("ObjectStack Framework"), updated badges (v4.0.1, 6,507 tests passing), fixed stale clone URL (spec.git→framework.git), added all missing packages (driver-sql,driver-turso,plugin-audit,plugin-setup,service-feed,service-automation,service-ai,service-realtime,service-i18n), updated codebase metrics (27 packages, 200 Zod schema files, 1,600+ exported schemas, 8,750+.describe()annotations, 6,507 tests passing), and restructured sections to match the current monorepo layout.
- AI Chat agent selector missing
data_chatandmetadata_assistant— FixedGET /api/v1/ai/agentsreturning 404, which caused the Studio AI Chat panel to show only "General Chat". There were two root causes addressed by this fix:- Kernel bootstrap timing (
packages/core/src/kernel.ts): 'core' service in-memory fallbacks (e.g. the 'metadata' service) were only injected invalidateSystemRequirements()which runs AFTER all pluginstart()methods execute. This meantctx.getService('metadata')always threw duringAIServicePlugin.start()when no explicitMetadataPluginwas loaded. Fix: addedpreInjectCoreFallbacks()called between Phase 1 (init) and Phase 2 (start), ensuring all core service fallbacks are available before any plugin'sstart()runs. - Shadowed variable (
packages/services/service-ai/src/plugin.ts): a redundant secondctx.getService('metadata')call declared a newconst metadataServicethat shadowed the outerlet metadataServiceand failed silently, preventingbuildAgentRoutes()from being called even if the metadata service was available. Fix: reuse the already-resolved outer variable. Additionally, added a fallback inDispatcherPlugin.start()that recovers AI routes from thekernel.__aiRoutescache in case theai:routeshook fires before the listener is registered (timing edge case).
- Kernel bootstrap timing (
- ObjectQLPlugin: cold-start metadata restoration —
ObjectQLPlugin.start()now callsprotocol.loadMetaFromDb()after driver initialization and before schema sync, restoring all persisted metadata (objects, views, apps, etc.) from thesys_metadatatable into the in-memorySchemaRegistry. Previously, user-created custom objects were lost after kernel cold starts or redeployments because the hydration step was missing. The fix gracefully degrades in in-memory-only or first-run scenarios wheresys_metadatadoes not yet exist. - Studio Vercel API routes returning HTML instead of JSON — Adopted the
same Vercel deployment pattern used by
hotcrm: committedapi/[[...route]].jscatch-all route so Vercel detects it pre-build, switched esbuild output from CJS to ESM (fixes"type": "module"conflict), and changed the bundle output toapi/_handler.js(a separate file that the committed wrapper re-exports). This avoids both Vercel's TS compilation overwriting the bundle (ERR_MODULE_NOT_FOUND) and the "File not found" error from deleting source files during build. AddedcreateRequirebanner to the esbuild config so that CJS dependencies (knex/tarn) canrequire()Node.js built-in modules likeeventswithout the "Dynamic require is not supported" error. Addedfunctions.includeFilesinvercel.jsonto include native addons (better-sqlite3,@libsql/client) that esbuild cannot bundle. Added a build step to copy native external modules from the monorepo rootnode_modules/into the studio's localnode_modules/, since pnpm's strict mode (unlike hotcrm'sshamefully-hoist) doesn't symlink transitive native dependencies into app-levelnode_modules/. Updated rewrites to match:/api/:path*→/api/[[...route]]. - Studio CORS error on Vercel temporary/preview domains — Changed
VITE_SERVER_URLfrom hardcodedhttps://play.objectstack.aito""(empty string / same-origin) invercel.jsonso each deployment — including previews — calls its own serverless function instead of the production API cross-origin. Also added Hono CORS middleware toapps/studio/server/index.tsas a safety net for any remaining cross-origin scenarios; dynamically allows all*.vercel.appsubdomains, explicitly listed Vercel deployment URLs, and localhost. ExtractedgetVercelOrigins()helper to keep CORS and better-authtrustedOriginsallowlists in sync. - Client test aligned with removed
ai.chatmethod — Updated@objectstack/clienttest suite to match the current API surface whereai.chat()was removed in favour of the Vercel AI SDKuseChat()hook. The obsolete test that calledclient.ai.chat()now asserts the method is absent, fixing the CI@objectstack/client#testfailure.
-
Metadata Assistant Agent (
service-ai) — Newmetadata_assistantagent definition that binds all 6 metadata management tools (create_object,add_field,modify_field,delete_field,list_objects,describe_object). Includes a tailored system prompt that guides the AI to use snake_case naming, verify existing schemas before modifications, and warn about destructive operations. Configured withreactplanning strategy (10 iterations, replan enabled) for multi-step schema design conversations. -
Tool Confirmation Flags — Added
requiresConfirmation: truetocreate_objectanddelete_fieldtool definitions. These destructive/creation operations now signal to the frontend that user approval is needed before execution. -
Frontend Tool Call Display (
AiChatPanel) — Enhanced the AI Chat Panel to render tool invocation parts from the Vercel AI SDK v6 stream protocol. Displays tool call status with visual indicators:- Calling: Spinner animation with tool name and argument summary
- Confirmation: Yellow-bordered card with Approve/Deny buttons for
requiresConfirmationtools - Success: Green success indicator with result preview
- Error: Red error indicator with error message
- Denied: Muted indicator for user-denied operations
-
Operation Confirmation Mechanism — Integrated the Vercel AI SDK
addToolApprovalResponsehook to support approval/denial workflows for tools marked withrequiresConfirmation. When the server sends anapproval-requestedstate, the chat panel shows Approve and Deny buttons. User decisions are sent back to the server to continue or abort the tool execution. -
Metadata Management Tools (
service-ai) — Added 6 built-in AI tools for metadata CRUD operations, each defined as a first-classToolmetadata file usingdefineTool()from@objectstack/spec/ai:create-object.tool.ts— Creates a new data object with schema validationadd-field.tool.ts— Adds a field to an existing objectmodify-field.tool.ts— Modifies field properties on an objectdelete-field.tool.ts— Removes a field from an objectlist-metadata-objects.tool.ts— Lists all registered metadata objectsdescribe-metadata-object.tool.ts— Returns full schema details of an object
Each
.tool.tsfile is an independent metadata unit withname,label,description,category,builtIn, andparameters— following the same.object.ts/.view.tsmetadata file convention. Handler factories remain inmetadata-tools.tsand bind handlers atai:readytime viaregisterMetadataTools(registry, { metadataService }). 79 unit tests covering tool metadata properties, handler execution, input validation, error handling, dual registration with data tools, and a full lifecycle test. -
Agent Skills —
skills/directory (agentskills.io) — Createdskills/folder at repository root following the agentskills.io specification. Five expert-knowledge skills with hand-writtenSKILL.mdfiles andreferences/quick-lookup tables:skills/schema-design/— Data schema design (Object, Field, Validation, Index)skills/ui-design/— UI protocol (View, App, Dashboard, Report, Action)skills/automation-design/— Automation (Flow, Workflow, Trigger, Approval)skills/ai-agent-design/— AI Agent protocol (Agent, Skill, RAG, Tool)skills/api-design/— API protocol (REST endpoints, Discovery, Datasource) EachSKILL.mdincludes YAML frontmatter (name,description,license,metadata), domain rules, usage guidance, best practices, common pitfalls, and code examples. Zod schema files remain the single source of truth; skills reference them for validation.
-
Discovery Schema —
ServiceStatusenum &handlerReadyfield — Added'registered'status toServiceInfoSchemato distinguish routes that are declared in the dispatcher table but whose HTTP handler has not been verified. Added optionalhandlerReadyboolean field (omitted = unverified/unknown) so clients can filter handler-ready services before displaying endpoints when the value is explicitlytrue. -
Discovery Schema —
RouteHealthReportSchema— New schema for automated route/handler coverage reporting at startup. Includes per-route health entries (pass,fail,missing,skip) and summary counters. -
Dispatcher Schema —
DispatcherErrorCode&DispatcherErrorResponseSchema— Semantic error codes (404/405/501/503) with machine-readabletypefield (ROUTE_NOT_FOUND,METHOD_NOT_ALLOWED,NOT_IMPLEMENTED,SERVICE_UNAVAILABLE) and developer-facinghintstrings. -
Dispatcher Schema —
/healthroute — Added health endpoint toDEFAULT_DISPATCHER_ROUTES. -
REST API Plugin —
handlerStatusfield — AddedhandlerStatus(implemented,stub,planned) toRestApiEndpointSchemato track handler implementation readiness. -
REST API Plugin —
RouteCoverageReportSchema— Schema for adapter-generated coverage reports listing every declared endpoint and its implementation status. -
aiv6 as a dependency of@objectstack/specfor type re-exports
- Removed
valuefield from data API responses — ThefindDataprotocol implementation no longer returns the deprecatedvaluefield alongsiderecords. Onlyrecordsis returned, matching theFindDataResponseSchemaspec. All downstream consumers (Studio, server example, tests) updated to userecordsexclusively. OData-specific responses (ODataResponseSchema) retainvalueper the OData v4 standard — protocol-to-OData adaptation is handled in the HTTP dispatch layer.
- AI Chat Protocol Aligned with Vercel AI SDK — Removed custom AI chat protocol
types and Zod schemas (
AIMessage,AIToolCall,AIStreamEvent,AiChatRequestSchema,AiChatResponseSchema) from@objectstack/spec. The canonical message, tool-call, and streaming types are now re-exported from the Vercel AI SDK (aiv6):ModelMessagereplacesAIMessageToolCallPartreplacesAIToolCallToolResultPartreplacesAIToolResultTextStreamPart<ToolSet>replacesAIStreamEventIAIServiceandLLMAdaptermethod signatures now acceptModelMessage[]and returnTextStreamPart<ToolSet>for streaming- Deprecated type aliases preserved for migration convenience
- NLQ, Suggest, and Insights protocols (ObjectStack-specific) are retained
@objectstack/service-aimigrated to Vercel AI SDK types — All source files and tests now use canonical Vercel types (ModelMessage,ToolCallPart,ToolResultPart,TextStreamPart<ToolSet>) instead of deprecated aliases:ToolRegistry.execute()acceptsToolCallPartand returnsToolExecutionResult(extendsToolResultPartwithisError?: boolean)- Tool call loop in
AIService.chatWithTools()constructs properAssistantModelMessageandToolModelMessagewith Vercel-format content arrays MemoryLLMAdapter.streamChat()emits VercelTextStreamPart<ToolSet>events- Conversation services serialize/deserialize
ModelMessageunion to flat DB columns - All 158 service-ai tests updated and passing
- Runtime Dispatcher — semantic error differentiation —
HttpDispatcher.dispatch()now returns typed 404 (ROUTE_NOT_FOUND) with diagnostic info instead of bare{ handled: false }. AddedrouteNotFound()(404) helper method. - Runtime Dispatcher —
/healthhandler — Added health endpoint returningstatus,timestamp,version, anduptime. - Runtime Dispatcher —
handlerReadyin discovery —getDiscoveryInfo()now emitshandlerReady: truefor services with confirmed handlers andhandlerReady: falsefor unavailable services. - Dispatcher Plugin — semantic 404 —
sendResult()now returnsROUTE_NOT_FOUNDerror type with a hint pointing to the discovery endpoint. Added/healthhandler registration. - Studio — handler-ready filtering —
useApiDiscovery()now checks bothenabledandhandlerReady(orstatus === 'available' | 'degraded'for backward compatibility) before displaying service endpoints in the UI.
AiChatRequestSchema/AiChatResponseSchemaZod schemas from@objectstack/spec/api— the AI chat wire protocol now uses Vercel AI SDK's data stream format (toDataStreamResponse())aiChatmethod fromIObjectStackAPIand client SDK — consumers should use@ai-sdk/react/useChatdirectly- AI
/chatendpoint fromDEFAULT_AI_ROUTESplugin REST API definition
aiv6 as a dependency of@objectstack/specfor type re-exports- Vercel AI Data Stream Protocol support on
/api/v1/ai/chat— The chat endpoint now supports dual-mode responses:- Streaming (default): When
streamis notfalse, returns Vercel Data Stream Protocol frames (0:text,9:tool-call,d:finish, etc.), directly consumable by@ai-sdk/react/useChat - JSON (legacy): When
stream: false, returns the original JSON response - Accepts Vercel useChat flat body format (
system,model,temperature,maxTokensas top-level fields) alongside the legacy{ messages, options } systemPrompt/systemfield is prepended as a system message- Message validation now accepts Vercel multi-part array content
RouteResponse.vercelDataStreamflag signals HTTP server layer to encode events using the Vercel Data Stream frame format
- Streaming (default): When
VercelLLMAdapter— Production adapter wrapping Vercel AI SDK'sgenerateText/streamTextfor any compatible model provider (OpenAI, Anthropic, Google, Ollama, etc.)vercel-stream-encoder.ts— Utilities (encodeStreamPart,encodeVercelDataStream) to convertTextStreamPart<ToolSet>events into Vercel Data Stream wire-format frames- 176 service-ai tests passing (18 new tests for stream encoder, route dual-mode, systemPrompt, flat options, array content)
- Version Alignment Patch — Unified all package versions to
4.0.1. Previously,@objectstack/driver-sqland@objectstack/driver-tursowere at3.3.2, example packages were at3.0.26, and the root monorepo was at3.0.8while all other@objectstack/*packages were at4.0.0. All packages now share a single, consistent version number aligned with the changesetfixedgroup configuration.
@objectstack/service-realtime—sys_presenceSystem Object — Registers thesys_presencesystem object in theservice-realtimepackage as the canonical Presence domain object. Fields align with thePresenceStateSchemaprotocol definition (user_id,session_id,status,last_seen,current_location,device,custom_status,metadata).RealtimeServicePluginnow auto-registers the object via theapp.com.objectstack.service.realtimeservice convention. AddedSystemObjectName.PRESENCEconstant ('sys_presence') to@objectstack/spec/system.@objectstack/service-ai— Data Chatbot: Tool Call Loop & Agent Runtime — Implements an Airtable Copilot-style data conversation Chatbot with full-stack support:AIService.chatWithTools()— automatic multi-round LLM ↔ tool call loop withmaxIterationssafety limit, parallel tool execution, and forced final responseAIResult.toolCalls— new field on the AI result contract so adapters can return tool call requests from the LLMChatWithToolsOptions— new contract interface extendingAIRequestOptions- 5 built-in data tools:
list_objects,describe_object,query_records,get_record,aggregate_data— with parameter schemas, limit capping (max 200), and error handling registerDataTools(registry, context)— factory to register all data tools againstIDataEngine+IMetadataServiceAgentRuntime— loads agent metadata, builds system prompts from instructions + UI context (objectName,recordId,viewName), resolves agent tool references against theToolRegistrybuildAgentRoutes()— newPOST /api/v1/ai/agents/:agentName/chatroute with agent lookup, active-check, context injection, andchatWithToolsintegrationDATA_CHAT_AGENT— built-indata_chatagent spec with role, instructions, guardrails, planning config, and tool declarationsAIServicePluginauto-registers data tools anddata_chatagent whenIDataEngine+IMetadataServiceare available in the kernel- 42 new test cases covering tool call loop, data tools, agent runtime, agent routes, and agent spec validation
@objectstack/service-ai— ObjectQL-backed persistent ConversationService — NewObjectQLConversationServiceimplementsIAIConversationServiceusingIDataEnginefor durable conversation and message storage across service restarts:ai_conversationsandai_messagessystem object definitions (namespaceai)- Full CRUD:
create,get,list(with userId/agentId/limit/cursor filters),addMessage(with toolCalls/toolCallId support), anddelete(cascade) AIServicePluginauto-detectsIDataEnginein the kernel service registry and usesObjectQLConversationServicewhen available, falling back toInMemoryConversationServicefor dev/test environmentsAIServicePluginOptions.conversationServiceallows explicit override- Plugin registers AI system objects via
app.com.objectstack.service-aiservice - 16 new test cases covering all five interface methods plus edge cases
- Promoted
LLMAdapterinterface to@objectstack/spec/contracts— Moved theLLMAdapteradapter contract from@objectstack/service-aiinternal types to the canonical protocol layer (packages/spec/src/contracts/llm-adapter.ts). Third-party adapter implementations (OpenAI, Anthropic, Ollama, etc.) can now depend solely on@objectstack/specfor type alignment.service-aire-exports the interface for backward compatibility.
- Changeset fixed versioning — add driver-sql and driver-turso — Added
@objectstack/driver-sqland@objectstack/driver-tursoto the changesetfixedversioning group in.changeset/config.json. These packages were missing from the group, causing them to be published as3.3.2instead of4.0.0during the v4.0.0 release. All future releases will now keep these driver packages in sync with the rest of the ecosystem. - ObjectQL build failure — Fixed TypeScript TS2345 errors in
packages/objectql/src/protocol.tswhereSchemaRegistry.registerItem()calls failed type checking for thekeyFieldparameter. Applied'name' as anycast consistent with the established codebase pattern. - ObjectQL
loadMetaFromDb— Fixed metadata hydration forobjecttype records to useSchemaRegistry.registerObject()instead ofregisterItem(), resolving a mismatch where objects registered viaregisterItemcould not be retrieved viagetItem('object', ...). - Adapter discovery endpoints — Fixed discovery route in Hono, SvelteKit, Nuxt, Next.js,
and Fastify adapters to serve discovery info at the API prefix root (e.g.,
GET /api) instead of a/discoverysubpath. Updated.well-known/objectstackredirects accordingly. - Client feed namespace routing — Fixed
ObjectStackClient.feedmethods to use thedataroute (/api/v1/data/{object}/{recordId}/feed) instead of a separate/api/v1/feedroute, matching the actual server-side routing where feed is a sub-resource of data.
@objectstack/service-ai— Unified AI capability service plugin — New kernel plugin providing standardized AI service integration:- Registers as kernel
'ai'service conforming toIAIServicecontract - LLM adapter layer with provider abstraction (
LLMAdapterinterface) and built-inMemoryLLMAdapterfor testing/development ToolRegistryfor metadata/business tool registration and executionInMemoryConversationServiceimplementingIAIConversationServicefor multi-turn conversation management with message persistence- REST/SSE route self-registration (
/api/v1/ai/chat,/api/v1/ai/chat/stream,/api/v1/ai/complete,/api/v1/ai/models,/api/v1/ai/conversations) - Plugin lifecycle hooks (
ai:ready,ai:routes) for extensibility
- Registers as kernel
- Expanded
IAIServicecontract — Added streaming (streamChat), tool calling protocol (AIToolDefinition,AIToolCall,AIToolResult,AIMessageWithTools,AIRequestOptionsWithTools,AIStreamEvent), and conversation management (IAIConversationService,AIConversation) topackages/spec/src/contracts/ai-service.ts @objectstack/plugin-setup— Platform Setup App plugin — New internal plugin (packages/plugins/plugin-setup) that owns and finalizes the platform Setup App. Ships four built-in Setup Areas (Administration, Platform, System, AI) as empty skeletons. Other plugins contribute navigation items via thesetupNavservice during theirinitphase. Atstart, SetupPlugin merges all contributions, filters out empty areas, and registers the finalized Setup App as an internal platform app. This establishes clear architectural separation: spec = protocol only, objectql = data/query only, plugins = system feature and UI composition.
- Unified API query syntax documentation with Spec canonical format — Rewrote
content/docs/protocol/objectql/query-syntax.mdxandcontent/docs/guides/contracts/data-engine.mdxto align all examples, interface definitions, and field names with the canonicalQuerySchema,FilterConditionSchema, andEngineQueryOptionsSchemafrom@objectstack/spec. All query examples now usewhere+ MongoDB-style$opobject syntax (replacing legacy tuple/filters/三元组 format),orderBy(replacingsort),groupBy(replacinggroup_by), andaggregationsarray (replacingaggregateobject map).IDataEnginecontract documentation updated to reflect the real interface (find/findOne/insert/update/delete/count/aggregate). Added legacy compatibility sections clearly marking tuple/array syntax as UI-builder input only, with migration guidance.
- Studio Vercel deployment — switched from InMemoryDriver to TursoDriver — The Studio serverless
API entrypoint (
apps/studio/api/index.ts) now uses@objectstack/driver-turso(TursoDriver) instead of@objectstack/driver-memory(InMemoryDriver) for Vercel deployments. In production, the driver connects to a Turso cloud database viaTURSO_DATABASE_URLandTURSO_AUTH_TOKENenvironment variables (remote mode). For local development without those variables, it falls back to:memory:(ephemeral SQLite). This ensures data persistence across serverless function invocations on Vercel. The browser MSW mock kernel remains unchanged (InMemoryDriver).
- Metadata DB persistence —
saveMetaItem()now writes to database — The protocol implementation (ObjectStackProtocolImplementation.saveMetaItem()) now persists metadata to thesys_metadatatable viaIDataEnginein addition to the in-memorySchemaRegistry. Previously, metadata saved viaPUT /api/v1/meta/:type/:namewas lost on server restart. AddedloadMetaFromDb()bootstrap method to hydrate the registry from the database on startup.getMetaItem()andgetMetaItems()now fall back to database queries when items are not found in the in-memory registry. Discovery endpoint metadata status upgraded fromdegradedtoavailable. Graceful degradation: if the database is unavailable, operations fall back to memory-only mode with a warning. - Vercel API always returns HTML — serverless function entrypoint not found — The
bundle-api.mjsscript was emittingapi/index.jsat the project root, butvercel.jsonsetsoutputDirectory: "dist", so Vercel could not discover the serverless function and fell back to the SPA HTML route for all/api/*requests. Changed esbuildoutfiletodist/api/index.jsand added explicitfunctionsconfig invercel.jsonwith@vercel/node@3runtime.
- Batch schema sync for remote DDL in kernel bootstrap —
ObjectQLPlugin.syncRegisteredSchemas()now groups objects by driver and usessyncSchemasBatch()when the driver advertisessupports.batchSchemaSync = true. This reduces the number of remote DDL round-trips from roughly N×(2–3) individual calls (introspection + optional PRAGMA + DDL write per object) to a small constant number of batchedclient.batch()calls, cutting cold-start times from 58+ seconds to under 10 seconds for 100+ objects on remote drivers (e.g. Turso cloud). Falls back to sequentialsyncSchema()per object for drivers without batch support or if the batched calls fail at runtime. AddedbatchSchemaSynccapability flag toDriverCapabilitiesSchema, optionalsyncSchemasBatch()toIDataDriver, andRemoteTransport.syncSchemasBatch()using@libsql/client'sbatch()API. @objectstack/driver-turso— dual transport architecture — TursoDriver now supports three transport modes:local,replica, andremote. Remote mode (url: 'libsql://...') enables pure cloud-only queries via@libsql/clientSDK (HTTP/WebSocket) without requiring a local SQLite database or Knex. Transport mode is auto-detected from the URL or can be forced viaconfig.mode. The driver exposestransportModeandisRemoteproperties for runtime introspection. All IDataDriver methods (CRUD, bulk, transactions, schema sync) work identically across all modes. AddedRemoteTransportclass,TursoTransportModetype, and support for injecting a pre-configured@libsql/clientinstance viaconfig.client.
- Vercel deployment —
ERR_MODULE_NOT_FOUNDfor@objectstack/metadata— Fixed incorrectexportspaths in@objectstack/metadatapackage.jsonthat pointed directly to TypeScript source files (src/index.ts,src/node.ts) instead of compiled dist output. Node.js cannot import.tsfiles at runtime, causingERR_MODULE_NOT_FOUNDon Vercel. Updatedmain,types, andexportsto reference dist files (dist/index.js,dist/index.mjs,dist/node.mjs, etc.). Added a localtsup.config.tswith both entry points (src/index.ts,src/node.ts) and afilesfield to the package.json. Follows the same pattern as@objectstack/spec. - Vercel deployment —
ERR_MODULE_NOT_FOUNDfor@objectstack/service-feed— Fixed incorrectexportspaths inpackage.jsonfor all service packages that declare"type": "module". Whentsupbuilds an ESM package ("type": "module"), it outputs.jsfor ESM and.cjsfor CJS. However, the exports maps incorrectly referenced.mjs(ESM) and.js(CJS) — the convention for packages without"type": "module". This caused Node's ESM resolver to fail withERR_MODULE_NOT_FOUNDwhen Vercel tried to importdist/index.mjs(which doesn't exist). Affected packages:service-feed,service-automation,service-cache,service-realtime,service-job,service-queue,service-storage,service-analytics. @objectstack/driver-sqlDTS build failure — knex type resolution — Fixed a TypeScript declaration build failure caused by knex v3.2.3 declaring a non-existent.d.mtstypes file in its package.jsonexportsfield. WithmoduleResolution: "bundler", TypeScript could not resolve knex's type declarations, resulting in TS7016 and TS7006 errors during DTS generation. Added apathsmapping in the driver-sqltsconfig.jsonto direct TypeScript to the correctknex/types/index.d.tsfile. This also fixes cascade build failures in all downstream packages that depend on driver-sql.SqlDriver.syncSchema()— physical table name mismatch — Fixed the root cause of theno such table: sys_usererror:syncSchema()was ignoring theobjectparameter (physical table name likesys_user) and usingschema.name(FQN likesys__user) for DDL operations. The method now correctly passes the physical table name toinitObjects(). Additionally,initObjects()now supports atableNameproperty as defense-in-depth, preferring it overnamewhen both are present.- Login API error — database tables not created — Fixed a critical naming mismatch between
the FQN (Fully Qualified Name) used by SchemaRegistry (e.g.,
sys__userwith double underscore) and the physical table name derived byObjectSchema.create()(e.g.,sys_userwith single underscore).syncRegisteredSchemas()now uses thetableNameproperty from object definitions for DDL operations, ensuring tables are created with the correct physical name that matches what the auth adapter andSystemObjectNameconstants expect. SchemaRegistry.getObject()— protocol name resolution — Added a third fallback that matches objects by theirtableNameproperty (e.g.,getObject('sys_user')now correctly finds the object registered as FQNsys__user). This bridges protocol-layer names (SystemObjectName.USER = 'sys_user') with the registry's FQN naming convention.ObjectQL.resolveObjectName()— physical table name — Now returnsschema.tableName(the physical table/collection name) instead ofschema.name(the FQN) when available, ensuring driver SQL queries target the correct table.SqlDriver.ensureDatabaseExists()— multi-driver support — Extended database auto-creation to support MySQL (error codeER_BAD_DB_ERROR/ errno 1049) alongside PostgreSQL (error code3D000). SQLite is explicitly skipped (auto-creates files).SqlDriver.createDatabase()— MySQL support — Added MySQL-specific logic that connects without a database specified and usesCREATE DATABASE IF NOT EXISTS.
@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