ObjectStackObjectStack

Backward Compatibility Policy

Versioning strategy, deprecation timelines, breaking change policy, and migration support for ObjectStack

Backward Compatibility Policy

ObjectStack follows strict backward compatibility guarantees to ensure predictable upgrades and long-term stability for production deployments.

Applies to: @objectstack/spec and all packages in the ObjectStack ecosystem.


Versioning Strategy

ObjectStack follows Semantic Versioning 2.0.0 (MAJOR.MINOR.PATCH):

Version ComponentWhen IncrementedGuarantee
MAJOR (X.0.0)Incompatible API changesMay contain breaking changes
MINOR (0.X.0)New features, backward-compatibleExisting code continues to work
PATCH (0.0.X)Bug fixes, backward-compatibleNo behavior changes, only fixes

SemVer Guarantees

  • Zod schemas are part of the public API surface. Adding optional properties is a MINOR change; removing or renaming properties is a MAJOR change.
  • TypeScript types inferred from Zod (z.infer<typeof Schema>) follow the same guarantees as their source schemas.
  • Helper functions (e.g., defineStack, defineStudioPlugin) maintain their call signatures within a MAJOR version.
  • Input formatsdefineStack() accepts both array and map (Record) format for all named metadata collections. Both formats are guaranteed stable within a MAJOR version.
  • Enum values are append-only within a MAJOR version. Existing values are never removed or renamed in MINOR/PATCH releases.
  • Default values in schemas are not changed in MINOR/PATCH releases unless fixing a documented bug.
// These imports are guaranteed stable within a MAJOR version
import { FieldSchema, ObjectSchema } from '@objectstack/spec/data';
import { defineStack } from '@objectstack/spec';
import { defineStudioPlugin } from '@objectstack/spec/studio';

Deprecation Timeline

When a feature, schema property, or API is deprecated, ObjectStack follows a structured wind-down process:

Phase 1: Deprecation Notice (MINOR release)

  • Feature is marked @deprecated in JSDoc comments
  • Zod schema property gets a .describe('DEPRECATED: ...') annotation
  • Runtime warning is emitted on first use (once per session)
  • Migration path is documented in the CHANGELOG

Phase 2: Migration Period (minimum 2 MINOR releases)

  • Deprecated feature continues to function without behavior changes
  • Documentation is updated with migration guides
  • Code examples are updated to use the replacement
  • CLI tooling may provide automated migration commands

Phase 3: Removal (next MAJOR release)

  • Deprecated feature is removed from the schema
  • TypeScript types no longer include the property
  • Runtime code no longer supports the feature

Timeline Summary

flowchart TD
    A["v3.2.0 — feature deprecated (warning emitted)"] --> B["v3.3.0 — migration period continues"]
    B --> C["v3.4.0 — migration continues (minimum 2 minor releases)"]
    C --> D["v4.0.0 — feature removed (earliest possible removal)"]

Minimum guarantee: Deprecated features survive for at least 2 MINOR releases before they can be removed in the next MAJOR version.


Breaking Change Policy

What Constitutes a Breaking Change

Change TypeBreaking?Version Impact
Removing a schema propertyYesMAJOR
Renaming a schema propertyYesMAJOR
Changing a property from optional to requiredYesMAJOR
Narrowing a type (e.g., stringenum)YesMAJOR
Removing an enum valueYesMAJOR
Changing default valuesYesMAJOR
Adding a new optional propertyNoMINOR
Adding a new enum valueNoMINOR
Widening a type (e.g., enumstring)NoMINOR
Adding a new schema/exportNoMINOR
Fixing validation to match documented behaviorNoPATCH
Fixing typos in descriptionsNoPATCH

Breaking Change Process

  1. RFC (Request for Comments) — Breaking changes are proposed as GitHub issues with the breaking-change label.
  2. Review Period — Minimum 30-day community review period.
  3. Deprecation — The old behavior is deprecated in a MINOR release (see timeline above).
  4. Migration Guide — A detailed migration guide is published before the MAJOR release.
  5. Release — Breaking change ships in the next MAJOR version.

Migration Support

Linting Your Project

The CLI's lint command checks your metadata for style and convention issues and surfaces them. Adding --fix prints the suggested fix for each issue (dry-run; it does not modify files):

# Check metadata for style and convention issues
os lint

# Show what could be auto-fixed (dry-run)
os lint --fix

# Scan your source for deprecated ObjectStack patterns
os doctor --scan-deprecations

# Compare two configs and detect breaking changes between versions
os diff <before> <after> --breaking-only

There is no lint --deprecations flag — deprecation scanning lives on os doctor --scan-deprecations. An automated codemod command is referenced in the migration guides but is not yet available; until then, combine os doctor --scan-deprecations, os diff, and the CHANGELOG migration notes (below) to upgrade across MAJOR versions.

Migration Guides

Each MAJOR release includes:

  • CHANGELOG.md — Complete list of changes with migration notes
  • RELEASE_NOTES.md — High-level summary and upgrade instructions
  • Schema Diff — Use os diff <before> <after> to produce a machine-readable (--json) diff of breaking changes between two configs

Support Windows

VersionStatusSupport Level
Current MAJOR (N)ActiveFull feature development, bug fixes, security patches
Previous MAJOR (N-1)MaintenanceCritical bug fixes and security patches only
Older versions (N-2+)End of LifeNo support; upgrade recommended

Spec Package Guarantees

The @objectstack/spec package provides additional stability guarantees:

Schema Stability

  • All Zod schemas are validated by comprehensive test suites
  • Schema changes require both Zod and JSON Schema output validation
  • Property additions must include .describe() annotations and .optional() or .default() markers

Export Stability

  • All public exports are listed in the package's index.ts barrel files
  • Removing an export is always a MAJOR change
  • Internal modules (prefixed with _ or in internal/ directories) are not covered by SemVer guarantees

Runtime Behavior

  • Schema.parse() results are guaranteed consistent within a MAJOR version
  • Default values applied by .default() are stable within a MAJOR version
  • Validation error messages may change in MINOR/PATCH releases (do not rely on exact error text)

Pre-1.0 Disclaimer

During the 0.x development phase, MINOR versions may contain breaking changes. The full backward compatibility policy takes effect starting with version 1.0.0.


Reporting Compatibility Issues

If you encounter an unintended breaking change:

  1. Check the CHANGELOG — Verify the change was not documented as intentional.
  2. Open an issue — File a GitHub issue with the compatibility label.
  3. Include a reproduction — Provide a minimal code sample showing the breakage.
  4. Reference the version — Specify the exact versions where behavior changed.

On this page