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 Component | When Incremented | Guarantee |
|---|---|---|
| MAJOR (X.0.0) | Incompatible API changes | May contain breaking changes |
| MINOR (0.X.0) | New features, backward-compatible | Existing code continues to work |
| PATCH (0.0.X) | Bug fixes, backward-compatible | No 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 formats —
defineStack()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
@deprecatedin 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 Type | Breaking? | Version Impact |
|---|---|---|
| Removing a schema property | Yes | MAJOR |
| Renaming a schema property | Yes | MAJOR |
| Changing a property from optional to required | Yes | MAJOR |
Narrowing a type (e.g., string → enum) | Yes | MAJOR |
| Removing an enum value | Yes | MAJOR |
| Changing default values | Yes | MAJOR |
| Adding a new optional property | No | MINOR |
| Adding a new enum value | No | MINOR |
Widening a type (e.g., enum → string) | No | MINOR |
| Adding a new schema/export | No | MINOR |
| Fixing validation to match documented behavior | No | PATCH |
| Fixing typos in descriptions | No | PATCH |
Breaking Change Process
- RFC (Request for Comments) — Breaking changes are proposed as GitHub issues with the
breaking-changelabel. - Review Period — Minimum 30-day community review period.
- Deprecation — The old behavior is deprecated in a MINOR release (see timeline above).
- Migration Guide — A detailed migration guide is published before the MAJOR release.
- 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-onlyThere 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
| Version | Status | Support Level |
|---|---|---|
| Current MAJOR (N) | Active | Full feature development, bug fixes, security patches |
| Previous MAJOR (N-1) | Maintenance | Critical bug fixes and security patches only |
| Older versions (N-2+) | End of Life | No 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.tsbarrel files - Removing an export is always a MAJOR change
- Internal modules (prefixed with
_or ininternal/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:
- Check the CHANGELOG — Verify the change was not documented as intentional.
- Open an issue — File a GitHub issue with the
compatibilitylabel. - Include a reproduction — Provide a minimal code sample showing the breakage.
- Reference the version — Specify the exact versions where behavior changed.