Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 27 additions & 19 deletions content/docs/protocol/backward-compatibility.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,17 +13,21 @@ ObjectStack follows strict backward compatibility guarantees to ensure predictab

## Versioning Strategy

ObjectStack follows [Semantic Versioning 2.0.0](https://semver.org/) (`MAJOR.MINOR.PATCH`):
<Callout type="warn">
**While the launch window is open, a breaking change ships as a MINOR release — not a MAJOR one.** Every published `@objectstack/*` package versions in lockstep, so the version number alone is not an upgrade-safety signal. This rule is in force today and overrides the MAJOR/MINOR mapping in the tables below wherever they disagree; read [Launch Window](#launch-window-minor-releases-can-contain-breaking-changes) at the end of this page before you plan an upgrade.
</Callout>

ObjectStack follows [Semantic Versioning 2.0.0](https://semver.org/) (`MAJOR.MINOR.PATCH`). The table below describes what each component means; the launch-window rule above governs which component a breaking change actually lands in today.

| 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 |
| **MINOR** (0.X.0) | New features — and, during the launch window, breaking changes | Existing code may require migration; the [release notes](/docs/releases) lead with what broke |
| **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.
- **Zod schemas** are part of the public API surface. Adding optional properties is a MINOR change; removing or renaming properties is a breaking change, which during the launch window also ships in a MINOR release.
- **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.
Expand DownExpand Up@@ -58,23 +62,26 @@ When a feature, schema property, or API is deprecated, ObjectStack follows a str
- Code examples are updated to use the replacement
- CLI tooling may provide automated migration commands

### Phase 3: Removal (next MAJOR release)
### Phase 3: Removal (MINOR release, during the launch window)

- Deprecated feature is removed from the schema
- TypeScript types no longer include the property
- Runtime code no longer supports the feature
- The removal is called out in the [release notes](/docs/releases) and marked `**BREAKING**` in the changeset

Shipped examples: `17.2.0` retired `http_request_errors_total` and `sys_position.permissions` under [ADR-0049](https://github.com/objectstack-ai/objectstack/blob/main/docs/adr/0049-no-unenforced-security-properties.md) enforce-or-remove, and `15.1.0` removed `tenancy.strategy` and `tenancy.crossTenantAccess` — all three in **Minor Changes** sections.

### Timeline Summary

```mermaid
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)"]
C --> D["v3.5.0 — feature removed (earliest possible removal, MINOR)"]
```

<Callout type="warn">
**Minimum guarantee:** Deprecated features survive for at least **2 MINOR releases** before they can be removed in the next MAJOR version.
**Minimum guarantee:** Deprecated features survive for at least **2 MINOR releases** before they can be removed. During the launch window the removal itself lands in a MINOR release, so a MINOR bump is where you should expect a removal to arrive.
</Callout>

---
Expand All@@ -83,14 +90,16 @@ flowchart TD

### What Constitutes a Breaking Change

| Change Type | Breaking? | Version Impact |
Read the **Breaking?** column, not the version number: during the launch window every row below — breaking or not — ships in a MINOR or PATCH release, so the bump size does not tell you whether you have work to do.

| Change Type | Breaking? | Version Impact (launch window) |
|:---|:---|:---|
| 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 |
| Removing a schema property | **Yes** | MINOR |
| Renaming a schema property | **Yes** | MINOR |
| Changing a property from optional to required | **Yes** | MINOR |
| Narrowing a type (e.g., `string` → `enum`) | **Yes** | MINOR |
| Removing an enum value | **Yes** | MINOR |
| Changing default values | **Yes** | MINOR |
| Adding a new optional property | No | MINOR |
| Adding a new enum value | No | MINOR |
| Widening a type (e.g., `enum` → `string`) | No | MINOR |
Expand All@@ -101,10 +110,9 @@ flowchart TD
### 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.
2. **Deprecation** — The old behavior is deprecated in a MINOR release (see timeline above).
3. **Migration Guide** — A detailed migration guide is published before the removal lands, in the release notes for the version that carries it.
4. **Release** — During the launch window the breaking change ships in the next **MINOR** version, carrying a changeset entry marked `**BREAKING**`. `scripts/check-changeset-no-major.mjs` fails any pull request that declares a `major` bump, because under lockstep one `major` would promote all 69 published packages.

---

Expand DownExpand Up@@ -163,7 +171,7 @@ The `@objectstack/spec` package provides additional stability guarantees:
### Export Stability

- All public exports are listed in the package's `index.ts` barrel files
- Removing an export is always a MAJOR change
- Removing an export is always a breaking change; during the launch window it ships in a MINOR release
- Internal modules (prefixed with `_` or in `internal/` directories) are not covered by SemVer guarantees

### Runtime Behavior
Expand DownExpand Up@@ -196,7 +204,7 @@ MAJOR releases do still happen — 17.0.0 was cut precisely because its breaking

### When it stops applying

The versioning tables and deprecation timeline above describe the policy in its settled form; they take full effect when the launch window closes and a breaking change once again requires a MAJOR. Until then, **this section is the operative rule wherever the two disagree.**
The tables and deprecation timeline above now state this rule directly, so the page no longer contradicts itself. Classic SemVer — where a breaking change once again requires a MAJOR — is the settled form the project returns to once the launch window closes; the condition that closes the window is tracked separately and is deliberately not stated here. Until it closes, **this section is the operative rule wherever any part of this page disagrees.**

---

Expand Down
30 changes: 25 additions & 5 deletions content/docs/releases/index.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -44,8 +44,28 @@ These pages are curated summaries. For exhaustive, per-package detail:

## Versioning policy

ObjectStack follows [Semantic Versioning](https://semver.org). A **major**
release may remove or change schemas in `@objectstack/spec`, public APIs, CLI
flags, or environment variables — always with a migration path documented in
the release notes. **Minor** releases add capabilities without breaking
existing metadata or code. **Patch** releases fix bugs.
ObjectStack follows [Semantic Versioning](https://semver.org), with one
override that is in force today: **while the launch window is open, a breaking
change ships as a minor release.** All `@objectstack/*` packages version in
lockstep, so a single major bump would promote the whole platform; instead a
breaking change lands in a **minor** alongside a changeset entry marked
`**BREAKING**`, and `scripts/check-changeset-no-major.mjs` fails any pull
request that declares a major bump.

What that means when you read a version number:

- A **major** release may remove or change schemas in `@objectstack/spec`,
public APIs, CLI flags, or environment variables — always with a migration
path documented in the release notes.
- A **minor** release adds capabilities, and **may also remove or change those
same surfaces**. `17.2.0` retired `http_request_errors_total` and
`sys_position.permissions`; `15.1.0` removed `tenancy.strategy` and
`tenancy.crossTenantAccess` — all in minor releases. As the v17 notes put it,
17.1.0 and 17.2.0 are minors by version number, not by blast radius.
- A **patch** release fixes bugs.

⚠️ **The version number is not the upgrade-safety signal.** Read the release
note for the version you are moving to — each one leads with breaking changes
and migration steps — and see
[Backward Compatibility](/docs/protocol/backward-compatibility#launch-window-minor-releases-can-contain-breaking-changes)
for the full policy.
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 27 additions & 19 deletions content/docs/protocol/backward-compatibility.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,17 +13,21 @@ ObjectStack follows strict backward compatibility guarantees to ensure predictab

## Versioning Strategy

ObjectStack follows [Semantic Versioning 2.0.0](https://semver.org/) (`MAJOR.MINOR.PATCH`):
<Callout type="warn">
**While the launch window is open, a breaking change ships as a MINOR release — not a MAJOR one.** Every published `@objectstack/*` package versions in lockstep, so the version number alone is not an upgrade-safety signal. This rule is in force today and overrides the MAJOR/MINOR mapping in the tables below wherever they disagree; read [Launch Window](#launch-window-minor-releases-can-contain-breaking-changes) at the end of this page before you plan an upgrade.
</Callout>

ObjectStack follows [Semantic Versioning 2.0.0](https://semver.org/) (`MAJOR.MINOR.PATCH`). The table below describes what each component means; the launch-window rule above governs which component a breaking change actually lands in today.

| 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 |
| **MINOR** (0.X.0) | New features — and, during the launch window, breaking changes | Existing code may require migration; the [release notes](/docs/releases) lead with what broke |
| **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.
- **Zod schemas** are part of the public API surface. Adding optional properties is a MINOR change; removing or renaming properties is a breaking change, which during the launch window also ships in a MINOR release.
- **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.
Expand DownExpand Up@@ -58,23 +62,26 @@ When a feature, schema property, or API is deprecated, ObjectStack follows a str
- Code examples are updated to use the replacement
- CLI tooling may provide automated migration commands

### Phase 3: Removal (next MAJOR release)
### Phase 3: Removal (MINOR release, during the launch window)

- Deprecated feature is removed from the schema
- TypeScript types no longer include the property
- Runtime code no longer supports the feature
- The removal is called out in the [release notes](/docs/releases) and marked `**BREAKING**` in the changeset

Shipped examples: `17.2.0` retired `http_request_errors_total` and `sys_position.permissions` under [ADR-0049](https://github.com/objectstack-ai/objectstack/blob/main/docs/adr/0049-no-unenforced-security-properties.md) enforce-or-remove, and `15.1.0` removed `tenancy.strategy` and `tenancy.crossTenantAccess` — all three in **Minor Changes** sections.

### Timeline Summary

```mermaid
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)"]
C --> D["v3.5.0 — feature removed (earliest possible removal, MINOR)"]
```

<Callout type="warn">
**Minimum guarantee:** Deprecated features survive for at least **2 MINOR releases** before they can be removed in the next MAJOR version.
**Minimum guarantee:** Deprecated features survive for at least **2 MINOR releases** before they can be removed. During the launch window the removal itself lands in a MINOR release, so a MINOR bump is where you should expect a removal to arrive.
</Callout>

---
Expand All@@ -83,14 +90,16 @@ flowchart TD

### What Constitutes a Breaking Change

| Change Type | Breaking? | Version Impact |
Read the **Breaking?** column, not the version number: during the launch window every row below — breaking or not — ships in a MINOR or PATCH release, so the bump size does not tell you whether you have work to do.

| Change Type | Breaking? | Version Impact (launch window) |
|:---|:---|:---|
| 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 |
| Removing a schema property | **Yes** | MINOR |
| Renaming a schema property | **Yes** | MINOR |
| Changing a property from optional to required | **Yes** | MINOR |
| Narrowing a type (e.g., `string` → `enum`) | **Yes** | MINOR |
| Removing an enum value | **Yes** | MINOR |
| Changing default values | **Yes** | MINOR |
| Adding a new optional property | No | MINOR |
| Adding a new enum value | No | MINOR |
| Widening a type (e.g., `enum` → `string`) | No | MINOR |
Expand All@@ -101,10 +110,9 @@ flowchart TD
### 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.
2. **Deprecation** — The old behavior is deprecated in a MINOR release (see timeline above).
3. **Migration Guide** — A detailed migration guide is published before the removal lands, in the release notes for the version that carries it.
4. **Release** — During the launch window the breaking change ships in the next **MINOR** version, carrying a changeset entry marked `**BREAKING**`. `scripts/check-changeset-no-major.mjs` fails any pull request that declares a `major` bump, because under lockstep one `major` would promote all 69 published packages.

---

Expand DownExpand Up@@ -163,7 +171,7 @@ The `@objectstack/spec` package provides additional stability guarantees:
### Export Stability

- All public exports are listed in the package's `index.ts` barrel files
- Removing an export is always a MAJOR change
- Removing an export is always a breaking change; during the launch window it ships in a MINOR release
- Internal modules (prefixed with `_` or in `internal/` directories) are not covered by SemVer guarantees

### Runtime Behavior
Expand DownExpand Up@@ -196,7 +204,7 @@ MAJOR releases do still happen — 17.0.0 was cut precisely because its breaking

### When it stops applying

The versioning tables and deprecation timeline above describe the policy in its settled form; they take full effect when the launch window closes and a breaking change once again requires a MAJOR. Until then, **this section is the operative rule wherever the two disagree.**
The tables and deprecation timeline above now state this rule directly, so the page no longer contradicts itself. Classic SemVer — where a breaking change once again requires a MAJOR — is the settled form the project returns to once the launch window closes; the condition that closes the window is tracked separately and is deliberately not stated here. Until it closes, **this section is the operative rule wherever any part of this page disagrees.**

---

Expand Down
30 changes: 25 additions & 5 deletions content/docs/releases/index.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -44,8 +44,28 @@ These pages are curated summaries. For exhaustive, per-package detail:

## Versioning policy

ObjectStack follows [Semantic Versioning](https://semver.org). A **major**
release may remove or change schemas in `@objectstack/spec`, public APIs, CLI
flags, or environment variables — always with a migration path documented in
the release notes. **Minor** releases add capabilities without breaking
existing metadata or code. **Patch** releases fix bugs.
ObjectStack follows [Semantic Versioning](https://semver.org), with one
override that is in force today: **while the launch window is open, a breaking
change ships as a minor release.** All `@objectstack/*` packages version in
lockstep, so a single major bump would promote the whole platform; instead a
breaking change lands in a **minor** alongside a changeset entry marked
`**BREAKING**`, and `scripts/check-changeset-no-major.mjs` fails any pull
request that declares a major bump.

What that means when you read a version number:

- A **major** release may remove or change schemas in `@objectstack/spec`,
public APIs, CLI flags, or environment variables — always with a migration
path documented in the release notes.
- A **minor** release adds capabilities, and **may also remove or change those
same surfaces**. `17.2.0` retired `http_request_errors_total` and
`sys_position.permissions`; `15.1.0` removed `tenancy.strategy` and
`tenancy.crossTenantAccess` — all in minor releases. As the v17 notes put it,
17.1.0 and 17.2.0 are minors by version number, not by blast radius.
- A **patch** release fixes bugs.

⚠️ **The version number is not the upgrade-safety signal.** Read the release
note for the version you are moving to — each one leads with breaking changes
and migration steps — and see
[Backward Compatibility](/docs/protocol/backward-compatibility#launch-window-minor-releases-can-contain-breaking-changes)
for the full policy.
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 27 additions & 19 deletions content/docs/protocol/backward-compatibility.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,17 +13,21 @@ ObjectStack follows strict backward compatibility guarantees to ensure predictab

## Versioning Strategy

ObjectStack follows [Semantic Versioning 2.0.0](https://semver.org/) (`MAJOR.MINOR.PATCH`):
<Callout type="warn">
**While the launch window is open, a breaking change ships as a MINOR release — not a MAJOR one.** Every published `@objectstack/*` package versions in lockstep, so the version number alone is not an upgrade-safety signal. This rule is in force today and overrides the MAJOR/MINOR mapping in the tables below wherever they disagree; read [Launch Window](#launch-window-minor-releases-can-contain-breaking-changes) at the end of this page before you plan an upgrade.
</Callout>

ObjectStack follows [Semantic Versioning 2.0.0](https://semver.org/) (`MAJOR.MINOR.PATCH`). The table below describes what each component means; the launch-window rule above governs which component a breaking change actually lands in today.

| 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 |
| **MINOR** (0.X.0) | New features — and, during the launch window, breaking changes | Existing code may require migration; the [release notes](/docs/releases) lead with what broke |
| **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.
- **Zod schemas** are part of the public API surface. Adding optional properties is a MINOR change; removing or renaming properties is a breaking change, which during the launch window also ships in a MINOR release.
- **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.
Expand DownExpand Up@@ -58,23 +62,26 @@ When a feature, schema property, or API is deprecated, ObjectStack follows a str
- Code examples are updated to use the replacement
- CLI tooling may provide automated migration commands

### Phase 3: Removal (next MAJOR release)
### Phase 3: Removal (MINOR release, during the launch window)

- Deprecated feature is removed from the schema
- TypeScript types no longer include the property
- Runtime code no longer supports the feature
- The removal is called out in the [release notes](/docs/releases) and marked `**BREAKING**` in the changeset

Shipped examples: `17.2.0` retired `http_request_errors_total` and `sys_position.permissions` under [ADR-0049](https://github.com/objectstack-ai/objectstack/blob/main/docs/adr/0049-no-unenforced-security-properties.md) enforce-or-remove, and `15.1.0` removed `tenancy.strategy` and `tenancy.crossTenantAccess` — all three in **Minor Changes** sections.

### Timeline Summary

```mermaid
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)"]
C --> D["v3.5.0 — feature removed (earliest possible removal, MINOR)"]
```

<Callout type="warn">
**Minimum guarantee:** Deprecated features survive for at least **2 MINOR releases** before they can be removed in the next MAJOR version.
**Minimum guarantee:** Deprecated features survive for at least **2 MINOR releases** before they can be removed. During the launch window the removal itself lands in a MINOR release, so a MINOR bump is where you should expect a removal to arrive.
</Callout>

---
Expand All@@ -83,14 +90,16 @@ flowchart TD

### What Constitutes a Breaking Change

| Change Type | Breaking? | Version Impact |
Read the **Breaking?** column, not the version number: during the launch window every row below — breaking or not — ships in a MINOR or PATCH release, so the bump size does not tell you whether you have work to do.

| Change Type | Breaking? | Version Impact (launch window) |
|:---|:---|:---|
| 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 |
| Removing a schema property | **Yes** | MINOR |
| Renaming a schema property | **Yes** | MINOR |
| Changing a property from optional to required | **Yes** | MINOR |
| Narrowing a type (e.g., `string` → `enum`) | **Yes** | MINOR |
| Removing an enum value | **Yes** | MINOR |
| Changing default values | **Yes** | MINOR |
| Adding a new optional property | No | MINOR |
| Adding a new enum value | No | MINOR |
| Widening a type (e.g., `enum` → `string`) | No | MINOR |
Expand All@@ -101,10 +110,9 @@ flowchart TD
### 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.
2. **Deprecation** — The old behavior is deprecated in a MINOR release (see timeline above).
3. **Migration Guide** — A detailed migration guide is published before the removal lands, in the release notes for the version that carries it.
4. **Release** — During the launch window the breaking change ships in the next **MINOR** version, carrying a changeset entry marked `**BREAKING**`. `scripts/check-changeset-no-major.mjs` fails any pull request that declares a `major` bump, because under lockstep one `major` would promote all 69 published packages.

---

Expand DownExpand Up@@ -163,7 +171,7 @@ The `@objectstack/spec` package provides additional stability guarantees:
### Export Stability

- All public exports are listed in the package's `index.ts` barrel files
- Removing an export is always a MAJOR change
- Removing an export is always a breaking change; during the launch window it ships in a MINOR release
- Internal modules (prefixed with `_` or in `internal/` directories) are not covered by SemVer guarantees

### Runtime Behavior
Expand DownExpand Up@@ -196,7 +204,7 @@ MAJOR releases do still happen — 17.0.0 was cut precisely because its breaking

### When it stops applying

The versioning tables and deprecation timeline above describe the policy in its settled form; they take full effect when the launch window closes and a breaking change once again requires a MAJOR. Until then, **this section is the operative rule wherever the two disagree.**
The tables and deprecation timeline above now state this rule directly, so the page no longer contradicts itself. Classic SemVer — where a breaking change once again requires a MAJOR — is the settled form the project returns to once the launch window closes; the condition that closes the window is tracked separately and is deliberately not stated here. Until it closes, **this section is the operative rule wherever any part of this page disagrees.**

---

Expand Down
30 changes: 25 additions & 5 deletions content/docs/releases/index.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -44,8 +44,28 @@ These pages are curated summaries. For exhaustive, per-package detail:

## Versioning policy

ObjectStack follows [Semantic Versioning](https://semver.org). A **major**
release may remove or change schemas in `@objectstack/spec`, public APIs, CLI
flags, or environment variables — always with a migration path documented in
the release notes. **Minor** releases add capabilities without breaking
existing metadata or code. **Patch** releases fix bugs.
ObjectStack follows [Semantic Versioning](https://semver.org), with one
override that is in force today: **while the launch window is open, a breaking
change ships as a minor release.** All `@objectstack/*` packages version in
lockstep, so a single major bump would promote the whole platform; instead a
breaking change lands in a **minor** alongside a changeset entry marked
`**BREAKING**`, and `scripts/check-changeset-no-major.mjs` fails any pull
request that declares a major bump.

What that means when you read a version number:

- A **major** release may remove or change schemas in `@objectstack/spec`,
public APIs, CLI flags, or environment variables — always with a migration
path documented in the release notes.
- A **minor** release adds capabilities, and **may also remove or change those
same surfaces**. `17.2.0` retired `http_request_errors_total` and
`sys_position.permissions`; `15.1.0` removed `tenancy.strategy` and
`tenancy.crossTenantAccess` — all in minor releases. As the v17 notes put it,
17.1.0 and 17.2.0 are minors by version number, not by blast radius.
- A **patch** release fixes bugs.

⚠️ **The version number is not the upgrade-safety signal.** Read the release
note for the version you are moving to — each one leads with breaking changes
and migration steps — and see
[Backward Compatibility](/docs/protocol/backward-compatibility#launch-window-minor-releases-can-contain-breaking-changes)
for the full policy.
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 27 additions & 19 deletions content/docs/protocol/backward-compatibility.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,17 +13,21 @@ ObjectStack follows strict backward compatibility guarantees to ensure predictab

## Versioning Strategy

ObjectStack follows [Semantic Versioning 2.0.0](https://semver.org/) (`MAJOR.MINOR.PATCH`):
<Callout type="warn">
**While the launch window is open, a breaking change ships as a MINOR release — not a MAJOR one.** Every published `@objectstack/*` package versions in lockstep, so the version number alone is not an upgrade-safety signal. This rule is in force today and overrides the MAJOR/MINOR mapping in the tables below wherever they disagree; read [Launch Window](#launch-window-minor-releases-can-contain-breaking-changes) at the end of this page before you plan an upgrade.
</Callout>

ObjectStack follows [Semantic Versioning 2.0.0](https://semver.org/) (`MAJOR.MINOR.PATCH`). The table below describes what each component means; the launch-window rule above governs which component a breaking change actually lands in today.

| 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 |
| **MINOR** (0.X.0) | New features — and, during the launch window, breaking changes | Existing code may require migration; the [release notes](/docs/releases) lead with what broke |
| **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.
- **Zod schemas** are part of the public API surface. Adding optional properties is a MINOR change; removing or renaming properties is a breaking change, which during the launch window also ships in a MINOR release.
- **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.
Expand DownExpand Up@@ -58,23 +62,26 @@ When a feature, schema property, or API is deprecated, ObjectStack follows a str
- Code examples are updated to use the replacement
- CLI tooling may provide automated migration commands

### Phase 3: Removal (next MAJOR release)
### Phase 3: Removal (MINOR release, during the launch window)

- Deprecated feature is removed from the schema
- TypeScript types no longer include the property
- Runtime code no longer supports the feature
- The removal is called out in the [release notes](/docs/releases) and marked `**BREAKING**` in the changeset

Shipped examples: `17.2.0` retired `http_request_errors_total` and `sys_position.permissions` under [ADR-0049](https://github.com/objectstack-ai/objectstack/blob/main/docs/adr/0049-no-unenforced-security-properties.md) enforce-or-remove, and `15.1.0` removed `tenancy.strategy` and `tenancy.crossTenantAccess` — all three in **Minor Changes** sections.

### Timeline Summary

```mermaid
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)"]
C --> D["v3.5.0 — feature removed (earliest possible removal, MINOR)"]
```

<Callout type="warn">
**Minimum guarantee:** Deprecated features survive for at least **2 MINOR releases** before they can be removed in the next MAJOR version.
**Minimum guarantee:** Deprecated features survive for at least **2 MINOR releases** before they can be removed. During the launch window the removal itself lands in a MINOR release, so a MINOR bump is where you should expect a removal to arrive.
</Callout>

---
Expand All@@ -83,14 +90,16 @@ flowchart TD

### What Constitutes a Breaking Change

| Change Type | Breaking? | Version Impact |
Read the **Breaking?** column, not the version number: during the launch window every row below — breaking or not — ships in a MINOR or PATCH release, so the bump size does not tell you whether you have work to do.

| Change Type | Breaking? | Version Impact (launch window) |
|:---|:---|:---|
| 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 |
| Removing a schema property | **Yes** | MINOR |
| Renaming a schema property | **Yes** | MINOR |
| Changing a property from optional to required | **Yes** | MINOR |
| Narrowing a type (e.g., `string` → `enum`) | **Yes** | MINOR |
| Removing an enum value | **Yes** | MINOR |
| Changing default values | **Yes** | MINOR |
| Adding a new optional property | No | MINOR |
| Adding a new enum value | No | MINOR |
| Widening a type (e.g., `enum` → `string`) | No | MINOR |
Expand All@@ -101,10 +110,9 @@ flowchart TD
### 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.
2. **Deprecation** — The old behavior is deprecated in a MINOR release (see timeline above).
3. **Migration Guide** — A detailed migration guide is published before the removal lands, in the release notes for the version that carries it.
4. **Release** — During the launch window the breaking change ships in the next **MINOR** version, carrying a changeset entry marked `**BREAKING**`. `scripts/check-changeset-no-major.mjs` fails any pull request that declares a `major` bump, because under lockstep one `major` would promote all 69 published packages.

---

Expand DownExpand Up@@ -163,7 +171,7 @@ The `@objectstack/spec` package provides additional stability guarantees:
### Export Stability

- All public exports are listed in the package's `index.ts` barrel files
- Removing an export is always a MAJOR change
- Removing an export is always a breaking change; during the launch window it ships in a MINOR release
- Internal modules (prefixed with `_` or in `internal/` directories) are not covered by SemVer guarantees

### Runtime Behavior
Expand DownExpand Up@@ -196,7 +204,7 @@ MAJOR releases do still happen — 17.0.0 was cut precisely because its breaking

### When it stops applying

The versioning tables and deprecation timeline above describe the policy in its settled form; they take full effect when the launch window closes and a breaking change once again requires a MAJOR. Until then, **this section is the operative rule wherever the two disagree.**
The tables and deprecation timeline above now state this rule directly, so the page no longer contradicts itself. Classic SemVer — where a breaking change once again requires a MAJOR — is the settled form the project returns to once the launch window closes; the condition that closes the window is tracked separately and is deliberately not stated here. Until it closes, **this section is the operative rule wherever any part of this page disagrees.**

---

Expand Down
30 changes: 25 additions & 5 deletions content/docs/releases/index.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -44,8 +44,28 @@ These pages are curated summaries. For exhaustive, per-package detail:

## Versioning policy

ObjectStack follows [Semantic Versioning](https://semver.org). A **major**
release may remove or change schemas in `@objectstack/spec`, public APIs, CLI
flags, or environment variables — always with a migration path documented in
the release notes. **Minor** releases add capabilities without breaking
existing metadata or code. **Patch** releases fix bugs.
ObjectStack follows [Semantic Versioning](https://semver.org), with one
override that is in force today: **while the launch window is open, a breaking
change ships as a minor release.** All `@objectstack/*` packages version in
lockstep, so a single major bump would promote the whole platform; instead a
breaking change lands in a **minor** alongside a changeset entry marked
`**BREAKING**`, and `scripts/check-changeset-no-major.mjs` fails any pull
request that declares a major bump.

What that means when you read a version number:

- A **major** release may remove or change schemas in `@objectstack/spec`,
public APIs, CLI flags, or environment variables — always with a migration
path documented in the release notes.
- A **minor** release adds capabilities, and **may also remove or change those
same surfaces**. `17.2.0` retired `http_request_errors_total` and
`sys_position.permissions`; `15.1.0` removed `tenancy.strategy` and
`tenancy.crossTenantAccess` — all in minor releases. As the v17 notes put it,
17.1.0 and 17.2.0 are minors by version number, not by blast radius.
- A **patch** release fixes bugs.

⚠️ **The version number is not the upgrade-safety signal.** Read the release
note for the version you are moving to — each one leads with breaking changes
and migration steps — and see
[Backward Compatibility](/docs/protocol/backward-compatibility#launch-window-minor-releases-can-contain-breaking-changes)
for the full policy.
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 27 additions & 19 deletions content/docs/protocol/backward-compatibility.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,17 +13,21 @@ ObjectStack follows strict backward compatibility guarantees to ensure predictab

## Versioning Strategy

ObjectStack follows [Semantic Versioning 2.0.0](https://semver.org/) (`MAJOR.MINOR.PATCH`):
<Callout type="warn">
**While the launch window is open, a breaking change ships as a MINOR release — not a MAJOR one.** Every published `@objectstack/*` package versions in lockstep, so the version number alone is not an upgrade-safety signal. This rule is in force today and overrides the MAJOR/MINOR mapping in the tables below wherever they disagree; read [Launch Window](#launch-window-minor-releases-can-contain-breaking-changes) at the end of this page before you plan an upgrade.
</Callout>

ObjectStack follows [Semantic Versioning 2.0.0](https://semver.org/) (`MAJOR.MINOR.PATCH`). The table below describes what each component means; the launch-window rule above governs which component a breaking change actually lands in today.

| 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 |
| **MINOR** (0.X.0) | New features — and, during the launch window, breaking changes | Existing code may require migration; the [release notes](/docs/releases) lead with what broke |
| **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.
- **Zod schemas** are part of the public API surface. Adding optional properties is a MINOR change; removing or renaming properties is a breaking change, which during the launch window also ships in a MINOR release.
- **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.
Expand DownExpand Up@@ -58,23 +62,26 @@ When a feature, schema property, or API is deprecated, ObjectStack follows a str
- Code examples are updated to use the replacement
- CLI tooling may provide automated migration commands

### Phase 3: Removal (next MAJOR release)
### Phase 3: Removal (MINOR release, during the launch window)

- Deprecated feature is removed from the schema
- TypeScript types no longer include the property
- Runtime code no longer supports the feature
- The removal is called out in the [release notes](/docs/releases) and marked `**BREAKING**` in the changeset

Shipped examples: `17.2.0` retired `http_request_errors_total` and `sys_position.permissions` under [ADR-0049](https://github.com/objectstack-ai/objectstack/blob/main/docs/adr/0049-no-unenforced-security-properties.md) enforce-or-remove, and `15.1.0` removed `tenancy.strategy` and `tenancy.crossTenantAccess` — all three in **Minor Changes** sections.

### Timeline Summary

```mermaid
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)"]
C --> D["v3.5.0 — feature removed (earliest possible removal, MINOR)"]
```

<Callout type="warn">
**Minimum guarantee:** Deprecated features survive for at least **2 MINOR releases** before they can be removed in the next MAJOR version.
**Minimum guarantee:** Deprecated features survive for at least **2 MINOR releases** before they can be removed. During the launch window the removal itself lands in a MINOR release, so a MINOR bump is where you should expect a removal to arrive.
</Callout>

---
Expand All@@ -83,14 +90,16 @@ flowchart TD

### What Constitutes a Breaking Change

| Change Type | Breaking? | Version Impact |
Read the **Breaking?** column, not the version number: during the launch window every row below — breaking or not — ships in a MINOR or PATCH release, so the bump size does not tell you whether you have work to do.

| Change Type | Breaking? | Version Impact (launch window) |
|:---|:---|:---|
| 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 |
| Removing a schema property | **Yes** | MINOR |
| Renaming a schema property | **Yes** | MINOR |
| Changing a property from optional to required | **Yes** | MINOR |
| Narrowing a type (e.g., `string` → `enum`) | **Yes** | MINOR |
| Removing an enum value | **Yes** | MINOR |
| Changing default values | **Yes** | MINOR |
| Adding a new optional property | No | MINOR |
| Adding a new enum value | No | MINOR |
| Widening a type (e.g., `enum` → `string`) | No | MINOR |
Expand All@@ -101,10 +110,9 @@ flowchart TD
### 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.
2. **Deprecation** — The old behavior is deprecated in a MINOR release (see timeline above).
3. **Migration Guide** — A detailed migration guide is published before the removal lands, in the release notes for the version that carries it.
4. **Release** — During the launch window the breaking change ships in the next **MINOR** version, carrying a changeset entry marked `**BREAKING**`. `scripts/check-changeset-no-major.mjs` fails any pull request that declares a `major` bump, because under lockstep one `major` would promote all 69 published packages.

---

Expand DownExpand Up@@ -163,7 +171,7 @@ The `@objectstack/spec` package provides additional stability guarantees:
### Export Stability

- All public exports are listed in the package's `index.ts` barrel files
- Removing an export is always a MAJOR change
- Removing an export is always a breaking change; during the launch window it ships in a MINOR release
- Internal modules (prefixed with `_` or in `internal/` directories) are not covered by SemVer guarantees

### Runtime Behavior
Expand DownExpand Up@@ -196,7 +204,7 @@ MAJOR releases do still happen — 17.0.0 was cut precisely because its breaking

### When it stops applying

The versioning tables and deprecation timeline above describe the policy in its settled form; they take full effect when the launch window closes and a breaking change once again requires a MAJOR. Until then, **this section is the operative rule wherever the two disagree.**
The tables and deprecation timeline above now state this rule directly, so the page no longer contradicts itself. Classic SemVer — where a breaking change once again requires a MAJOR — is the settled form the project returns to once the launch window closes; the condition that closes the window is tracked separately and is deliberately not stated here. Until it closes, **this section is the operative rule wherever any part of this page disagrees.**

---

Expand Down
30 changes: 25 additions & 5 deletions content/docs/releases/index.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -44,8 +44,28 @@ These pages are curated summaries. For exhaustive, per-package detail:

## Versioning policy

ObjectStack follows [Semantic Versioning](https://semver.org). A **major**
release may remove or change schemas in `@objectstack/spec`, public APIs, CLI
flags, or environment variables — always with a migration path documented in
the release notes. **Minor** releases add capabilities without breaking
existing metadata or code. **Patch** releases fix bugs.
ObjectStack follows [Semantic Versioning](https://semver.org), with one
override that is in force today: **while the launch window is open, a breaking
change ships as a minor release.** All `@objectstack/*` packages version in
lockstep, so a single major bump would promote the whole platform; instead a
breaking change lands in a **minor** alongside a changeset entry marked
`**BREAKING**`, and `scripts/check-changeset-no-major.mjs` fails any pull
request that declares a major bump.

What that means when you read a version number:

- A **major** release may remove or change schemas in `@objectstack/spec`,
public APIs, CLI flags, or environment variables — always with a migration
path documented in the release notes.
- A **minor** release adds capabilities, and **may also remove or change those
same surfaces**. `17.2.0` retired `http_request_errors_total` and
`sys_position.permissions`; `15.1.0` removed `tenancy.strategy` and
`tenancy.crossTenantAccess` — all in minor releases. As the v17 notes put it,
17.1.0 and 17.2.0 are minors by version number, not by blast radius.
- A **patch** release fixes bugs.

⚠️ **The version number is not the upgrade-safety signal.** Read the release
note for the version you are moving to — each one leads with breaking changes
and migration steps — and see
[Backward Compatibility](/docs/protocol/backward-compatibility#launch-window-minor-releases-can-contain-breaking-changes)
for the full policy.
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 27 additions & 19 deletions content/docs/protocol/backward-compatibility.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,17 +13,21 @@ ObjectStack follows strict backward compatibility guarantees to ensure predictab

## Versioning Strategy

ObjectStack follows [Semantic Versioning 2.0.0](https://semver.org/) (`MAJOR.MINOR.PATCH`):
<Callout type="warn">
**While the launch window is open, a breaking change ships as a MINOR release — not a MAJOR one.** Every published `@objectstack/*` package versions in lockstep, so the version number alone is not an upgrade-safety signal. This rule is in force today and overrides the MAJOR/MINOR mapping in the tables below wherever they disagree; read [Launch Window](#launch-window-minor-releases-can-contain-breaking-changes) at the end of this page before you plan an upgrade.
</Callout>

ObjectStack follows [Semantic Versioning 2.0.0](https://semver.org/) (`MAJOR.MINOR.PATCH`). The table below describes what each component means; the launch-window rule above governs which component a breaking change actually lands in today.

| 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 |
| **MINOR** (0.X.0) | New features — and, during the launch window, breaking changes | Existing code may require migration; the [release notes](/docs/releases) lead with what broke |
| **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.
- **Zod schemas** are part of the public API surface. Adding optional properties is a MINOR change; removing or renaming properties is a breaking change, which during the launch window also ships in a MINOR release.
- **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.
Expand DownExpand Up@@ -58,23 +62,26 @@ When a feature, schema property, or API is deprecated, ObjectStack follows a str
- Code examples are updated to use the replacement
- CLI tooling may provide automated migration commands

### Phase 3: Removal (next MAJOR release)
### Phase 3: Removal (MINOR release, during the launch window)

- Deprecated feature is removed from the schema
- TypeScript types no longer include the property
- Runtime code no longer supports the feature
- The removal is called out in the [release notes](/docs/releases) and marked `**BREAKING**` in the changeset

Shipped examples: `17.2.0` retired `http_request_errors_total` and `sys_position.permissions` under [ADR-0049](https://github.com/objectstack-ai/objectstack/blob/main/docs/adr/0049-no-unenforced-security-properties.md) enforce-or-remove, and `15.1.0` removed `tenancy.strategy` and `tenancy.crossTenantAccess` — all three in **Minor Changes** sections.

### Timeline Summary

```mermaid
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)"]
C --> D["v3.5.0 — feature removed (earliest possible removal, MINOR)"]
```

<Callout type="warn">
**Minimum guarantee:** Deprecated features survive for at least **2 MINOR releases** before they can be removed in the next MAJOR version.
**Minimum guarantee:** Deprecated features survive for at least **2 MINOR releases** before they can be removed. During the launch window the removal itself lands in a MINOR release, so a MINOR bump is where you should expect a removal to arrive.
</Callout>

---
Expand All@@ -83,14 +90,16 @@ flowchart TD

### What Constitutes a Breaking Change

| Change Type | Breaking? | Version Impact |
Read the **Breaking?** column, not the version number: during the launch window every row below — breaking or not — ships in a MINOR or PATCH release, so the bump size does not tell you whether you have work to do.

| Change Type | Breaking? | Version Impact (launch window) |
|:---|:---|:---|
| 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 |
| Removing a schema property | **Yes** | MINOR |
| Renaming a schema property | **Yes** | MINOR |
| Changing a property from optional to required | **Yes** | MINOR |
| Narrowing a type (e.g., `string` → `enum`) | **Yes** | MINOR |
| Removing an enum value | **Yes** | MINOR |
| Changing default values | **Yes** | MINOR |
| Adding a new optional property | No | MINOR |
| Adding a new enum value | No | MINOR |
| Widening a type (e.g., `enum` → `string`) | No | MINOR |
Expand All@@ -101,10 +110,9 @@ flowchart TD
### 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.
2. **Deprecation** — The old behavior is deprecated in a MINOR release (see timeline above).
3. **Migration Guide** — A detailed migration guide is published before the removal lands, in the release notes for the version that carries it.
4. **Release** — During the launch window the breaking change ships in the next **MINOR** version, carrying a changeset entry marked `**BREAKING**`. `scripts/check-changeset-no-major.mjs` fails any pull request that declares a `major` bump, because under lockstep one `major` would promote all 69 published packages.

---

Expand DownExpand Up@@ -163,7 +171,7 @@ The `@objectstack/spec` package provides additional stability guarantees:
### Export Stability

- All public exports are listed in the package's `index.ts` barrel files
- Removing an export is always a MAJOR change
- Removing an export is always a breaking change; during the launch window it ships in a MINOR release
- Internal modules (prefixed with `_` or in `internal/` directories) are not covered by SemVer guarantees

### Runtime Behavior
Expand DownExpand Up@@ -196,7 +204,7 @@ MAJOR releases do still happen — 17.0.0 was cut precisely because its breaking

### When it stops applying

The versioning tables and deprecation timeline above describe the policy in its settled form; they take full effect when the launch window closes and a breaking change once again requires a MAJOR. Until then, **this section is the operative rule wherever the two disagree.**
The tables and deprecation timeline above now state this rule directly, so the page no longer contradicts itself. Classic SemVer — where a breaking change once again requires a MAJOR — is the settled form the project returns to once the launch window closes; the condition that closes the window is tracked separately and is deliberately not stated here. Until it closes, **this section is the operative rule wherever any part of this page disagrees.**

---

Expand Down
30 changes: 25 additions & 5 deletions content/docs/releases/index.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -44,8 +44,28 @@ These pages are curated summaries. For exhaustive, per-package detail:

## Versioning policy

ObjectStack follows [Semantic Versioning](https://semver.org). A **major**
release may remove or change schemas in `@objectstack/spec`, public APIs, CLI
flags, or environment variables — always with a migration path documented in
the release notes. **Minor** releases add capabilities without breaking
existing metadata or code. **Patch** releases fix bugs.
ObjectStack follows [Semantic Versioning](https://semver.org), with one
override that is in force today: **while the launch window is open, a breaking
change ships as a minor release.** All `@objectstack/*` packages version in
lockstep, so a single major bump would promote the whole platform; instead a
breaking change lands in a **minor** alongside a changeset entry marked
`**BREAKING**`, and `scripts/check-changeset-no-major.mjs` fails any pull
request that declares a major bump.

What that means when you read a version number:

- A **major** release may remove or change schemas in `@objectstack/spec`,
public APIs, CLI flags, or environment variables — always with a migration
path documented in the release notes.
- A **minor** release adds capabilities, and **may also remove or change those
same surfaces**. `17.2.0` retired `http_request_errors_total` and
`sys_position.permissions`; `15.1.0` removed `tenancy.strategy` and
`tenancy.crossTenantAccess` — all in minor releases. As the v17 notes put it,
17.1.0 and 17.2.0 are minors by version number, not by blast radius.
- A **patch** release fixes bugs.

⚠️ **The version number is not the upgrade-safety signal.** Read the release
note for the version you are moving to — each one leads with breaking changes
and migration steps — and see
[Backward Compatibility](/docs/protocol/backward-compatibility#launch-window-minor-releases-can-contain-breaking-changes)
for the full policy.
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 27 additions & 19 deletions content/docs/protocol/backward-compatibility.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,17 +13,21 @@ ObjectStack follows strict backward compatibility guarantees to ensure predictab

## Versioning Strategy

ObjectStack follows [Semantic Versioning 2.0.0](https://semver.org/) (`MAJOR.MINOR.PATCH`):
<Callout type="warn">
**While the launch window is open, a breaking change ships as a MINOR release — not a MAJOR one.** Every published `@objectstack/*` package versions in lockstep, so the version number alone is not an upgrade-safety signal. This rule is in force today and overrides the MAJOR/MINOR mapping in the tables below wherever they disagree; read [Launch Window](#launch-window-minor-releases-can-contain-breaking-changes) at the end of this page before you plan an upgrade.
</Callout>

ObjectStack follows [Semantic Versioning 2.0.0](https://semver.org/) (`MAJOR.MINOR.PATCH`). The table below describes what each component means; the launch-window rule above governs which component a breaking change actually lands in today.

| 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 |
| **MINOR** (0.X.0) | New features — and, during the launch window, breaking changes | Existing code may require migration; the [release notes](/docs/releases) lead with what broke |
| **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.
- **Zod schemas** are part of the public API surface. Adding optional properties is a MINOR change; removing or renaming properties is a breaking change, which during the launch window also ships in a MINOR release.
- **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.
Expand DownExpand Up@@ -58,23 +62,26 @@ When a feature, schema property, or API is deprecated, ObjectStack follows a str
- Code examples are updated to use the replacement
- CLI tooling may provide automated migration commands

### Phase 3: Removal (next MAJOR release)
### Phase 3: Removal (MINOR release, during the launch window)

- Deprecated feature is removed from the schema
- TypeScript types no longer include the property
- Runtime code no longer supports the feature
- The removal is called out in the [release notes](/docs/releases) and marked `**BREAKING**` in the changeset

Shipped examples: `17.2.0` retired `http_request_errors_total` and `sys_position.permissions` under [ADR-0049](https://github.com/objectstack-ai/objectstack/blob/main/docs/adr/0049-no-unenforced-security-properties.md) enforce-or-remove, and `15.1.0` removed `tenancy.strategy` and `tenancy.crossTenantAccess` — all three in **Minor Changes** sections.

### Timeline Summary

```mermaid
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)"]
C --> D["v3.5.0 — feature removed (earliest possible removal, MINOR)"]
```

<Callout type="warn">
**Minimum guarantee:** Deprecated features survive for at least **2 MINOR releases** before they can be removed in the next MAJOR version.
**Minimum guarantee:** Deprecated features survive for at least **2 MINOR releases** before they can be removed. During the launch window the removal itself lands in a MINOR release, so a MINOR bump is where you should expect a removal to arrive.
</Callout>

---
Expand All@@ -83,14 +90,16 @@ flowchart TD

### What Constitutes a Breaking Change

| Change Type | Breaking? | Version Impact |
Read the **Breaking?** column, not the version number: during the launch window every row below — breaking or not — ships in a MINOR or PATCH release, so the bump size does not tell you whether you have work to do.

| Change Type | Breaking? | Version Impact (launch window) |
|:---|:---|:---|
| 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 |
| Removing a schema property | **Yes** | MINOR |
| Renaming a schema property | **Yes** | MINOR |
| Changing a property from optional to required | **Yes** | MINOR |
| Narrowing a type (e.g., `string` → `enum`) | **Yes** | MINOR |
| Removing an enum value | **Yes** | MINOR |
| Changing default values | **Yes** | MINOR |
| Adding a new optional property | No | MINOR |
| Adding a new enum value | No | MINOR |
| Widening a type (e.g., `enum` → `string`) | No | MINOR |
Expand All@@ -101,10 +110,9 @@ flowchart TD
### 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.
2. **Deprecation** — The old behavior is deprecated in a MINOR release (see timeline above).
3. **Migration Guide** — A detailed migration guide is published before the removal lands, in the release notes for the version that carries it.
4. **Release** — During the launch window the breaking change ships in the next **MINOR** version, carrying a changeset entry marked `**BREAKING**`. `scripts/check-changeset-no-major.mjs` fails any pull request that declares a `major` bump, because under lockstep one `major` would promote all 69 published packages.

---

Expand DownExpand Up@@ -163,7 +171,7 @@ The `@objectstack/spec` package provides additional stability guarantees:
### Export Stability

- All public exports are listed in the package's `index.ts` barrel files
- Removing an export is always a MAJOR change
- Removing an export is always a breaking change; during the launch window it ships in a MINOR release
- Internal modules (prefixed with `_` or in `internal/` directories) are not covered by SemVer guarantees

### Runtime Behavior
Expand DownExpand Up@@ -196,7 +204,7 @@ MAJOR releases do still happen — 17.0.0 was cut precisely because its breaking

### When it stops applying

The versioning tables and deprecation timeline above describe the policy in its settled form; they take full effect when the launch window closes and a breaking change once again requires a MAJOR. Until then, **this section is the operative rule wherever the two disagree.**
The tables and deprecation timeline above now state this rule directly, so the page no longer contradicts itself. Classic SemVer — where a breaking change once again requires a MAJOR — is the settled form the project returns to once the launch window closes; the condition that closes the window is tracked separately and is deliberately not stated here. Until it closes, **this section is the operative rule wherever any part of this page disagrees.**

---

Expand Down
30 changes: 25 additions & 5 deletions content/docs/releases/index.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -44,8 +44,28 @@ These pages are curated summaries. For exhaustive, per-package detail:

## Versioning policy

ObjectStack follows [Semantic Versioning](https://semver.org). A **major**
release may remove or change schemas in `@objectstack/spec`, public APIs, CLI
flags, or environment variables — always with a migration path documented in
the release notes. **Minor** releases add capabilities without breaking
existing metadata or code. **Patch** releases fix bugs.
ObjectStack follows [Semantic Versioning](https://semver.org), with one
override that is in force today: **while the launch window is open, a breaking
change ships as a minor release.** All `@objectstack/*` packages version in
lockstep, so a single major bump would promote the whole platform; instead a
breaking change lands in a **minor** alongside a changeset entry marked
`**BREAKING**`, and `scripts/check-changeset-no-major.mjs` fails any pull
request that declares a major bump.

What that means when you read a version number:

- A **major** release may remove or change schemas in `@objectstack/spec`,
public APIs, CLI flags, or environment variables — always with a migration
path documented in the release notes.
- A **minor** release adds capabilities, and **may also remove or change those
same surfaces**. `17.2.0` retired `http_request_errors_total` and
`sys_position.permissions`; `15.1.0` removed `tenancy.strategy` and
`tenancy.crossTenantAccess` — all in minor releases. As the v17 notes put it,
17.1.0 and 17.2.0 are minors by version number, not by blast radius.
- A **patch** release fixes bugs.

⚠️ **The version number is not the upgrade-safety signal.** Read the release
note for the version you are moving to — each one leads with breaking changes
and migration steps — and see
[Backward Compatibility](/docs/protocol/backward-compatibility#launch-window-minor-releases-can-contain-breaking-changes)
for the full policy.
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 27 additions & 19 deletions content/docs/protocol/backward-compatibility.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,17 +13,21 @@ ObjectStack follows strict backward compatibility guarantees to ensure predictab

## Versioning Strategy

ObjectStack follows [Semantic Versioning 2.0.0](https://semver.org/) (`MAJOR.MINOR.PATCH`):
<Callout type="warn">
**While the launch window is open, a breaking change ships as a MINOR release — not a MAJOR one.** Every published `@objectstack/*` package versions in lockstep, so the version number alone is not an upgrade-safety signal. This rule is in force today and overrides the MAJOR/MINOR mapping in the tables below wherever they disagree; read [Launch Window](#launch-window-minor-releases-can-contain-breaking-changes) at the end of this page before you plan an upgrade.
</Callout>

ObjectStack follows [Semantic Versioning 2.0.0](https://semver.org/) (`MAJOR.MINOR.PATCH`). The table below describes what each component means; the launch-window rule above governs which component a breaking change actually lands in today.

| 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 |
| **MINOR** (0.X.0) | New features — and, during the launch window, breaking changes | Existing code may require migration; the [release notes](/docs/releases) lead with what broke |
| **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.
- **Zod schemas** are part of the public API surface. Adding optional properties is a MINOR change; removing or renaming properties is a breaking change, which during the launch window also ships in a MINOR release.
- **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.
Expand DownExpand Up@@ -58,23 +62,26 @@ When a feature, schema property, or API is deprecated, ObjectStack follows a str
- Code examples are updated to use the replacement
- CLI tooling may provide automated migration commands

### Phase 3: Removal (next MAJOR release)
### Phase 3: Removal (MINOR release, during the launch window)

- Deprecated feature is removed from the schema
- TypeScript types no longer include the property
- Runtime code no longer supports the feature
- The removal is called out in the [release notes](/docs/releases) and marked `**BREAKING**` in the changeset

Shipped examples: `17.2.0` retired `http_request_errors_total` and `sys_position.permissions` under [ADR-0049](https://github.com/objectstack-ai/objectstack/blob/main/docs/adr/0049-no-unenforced-security-properties.md) enforce-or-remove, and `15.1.0` removed `tenancy.strategy` and `tenancy.crossTenantAccess` — all three in **Minor Changes** sections.

### Timeline Summary

```mermaid
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)"]
C --> D["v3.5.0 — feature removed (earliest possible removal, MINOR)"]
```

<Callout type="warn">
**Minimum guarantee:** Deprecated features survive for at least **2 MINOR releases** before they can be removed in the next MAJOR version.
**Minimum guarantee:** Deprecated features survive for at least **2 MINOR releases** before they can be removed. During the launch window the removal itself lands in a MINOR release, so a MINOR bump is where you should expect a removal to arrive.
</Callout>

---
Expand All@@ -83,14 +90,16 @@ flowchart TD

### What Constitutes a Breaking Change

| Change Type | Breaking? | Version Impact |
Read the **Breaking?** column, not the version number: during the launch window every row below — breaking or not — ships in a MINOR or PATCH release, so the bump size does not tell you whether you have work to do.

| Change Type | Breaking? | Version Impact (launch window) |
|:---|:---|:---|
| 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 |
| Removing a schema property | **Yes** | MINOR |
| Renaming a schema property | **Yes** | MINOR |
| Changing a property from optional to required | **Yes** | MINOR |
| Narrowing a type (e.g., `string` → `enum`) | **Yes** | MINOR |
| Removing an enum value | **Yes** | MINOR |
| Changing default values | **Yes** | MINOR |
| Adding a new optional property | No | MINOR |
| Adding a new enum value | No | MINOR |
| Widening a type (e.g., `enum` → `string`) | No | MINOR |
Expand All@@ -101,10 +110,9 @@ flowchart TD
### 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.
2. **Deprecation** — The old behavior is deprecated in a MINOR release (see timeline above).
3. **Migration Guide** — A detailed migration guide is published before the removal lands, in the release notes for the version that carries it.
4. **Release** — During the launch window the breaking change ships in the next **MINOR** version, carrying a changeset entry marked `**BREAKING**`. `scripts/check-changeset-no-major.mjs` fails any pull request that declares a `major` bump, because under lockstep one `major` would promote all 69 published packages.

---

Expand DownExpand Up@@ -163,7 +171,7 @@ The `@objectstack/spec` package provides additional stability guarantees:
### Export Stability

- All public exports are listed in the package's `index.ts` barrel files
- Removing an export is always a MAJOR change
- Removing an export is always a breaking change; during the launch window it ships in a MINOR release
- Internal modules (prefixed with `_` or in `internal/` directories) are not covered by SemVer guarantees

### Runtime Behavior
Expand DownExpand Up@@ -196,7 +204,7 @@ MAJOR releases do still happen — 17.0.0 was cut precisely because its breaking

### When it stops applying

The versioning tables and deprecation timeline above describe the policy in its settled form; they take full effect when the launch window closes and a breaking change once again requires a MAJOR. Until then, **this section is the operative rule wherever the two disagree.**
The tables and deprecation timeline above now state this rule directly, so the page no longer contradicts itself. Classic SemVer — where a breaking change once again requires a MAJOR — is the settled form the project returns to once the launch window closes; the condition that closes the window is tracked separately and is deliberately not stated here. Until it closes, **this section is the operative rule wherever any part of this page disagrees.**

---

Expand Down
30 changes: 25 additions & 5 deletions content/docs/releases/index.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -44,8 +44,28 @@ These pages are curated summaries. For exhaustive, per-package detail:

## Versioning policy

ObjectStack follows [Semantic Versioning](https://semver.org). A **major**
release may remove or change schemas in `@objectstack/spec`, public APIs, CLI
flags, or environment variables — always with a migration path documented in
the release notes. **Minor** releases add capabilities without breaking
existing metadata or code. **Patch** releases fix bugs.
ObjectStack follows [Semantic Versioning](https://semver.org), with one
override that is in force today: **while the launch window is open, a breaking
change ships as a minor release.** All `@objectstack/*` packages version in
lockstep, so a single major bump would promote the whole platform; instead a
breaking change lands in a **minor** alongside a changeset entry marked
`**BREAKING**`, and `scripts/check-changeset-no-major.mjs` fails any pull
request that declares a major bump.

What that means when you read a version number:

- A **major** release may remove or change schemas in `@objectstack/spec`,
public APIs, CLI flags, or environment variables — always with a migration
path documented in the release notes.
- A **minor** release adds capabilities, and **may also remove or change those
same surfaces**. `17.2.0` retired `http_request_errors_total` and
`sys_position.permissions`; `15.1.0` removed `tenancy.strategy` and
`tenancy.crossTenantAccess` — all in minor releases. As the v17 notes put it,
17.1.0 and 17.2.0 are minors by version number, not by blast radius.
- A **patch** release fixes bugs.

⚠️ **The version number is not the upgrade-safety signal.** Read the release
note for the version you are moving to — each one leads with breaking changes
and migration steps — and see
[Backward Compatibility](/docs/protocol/backward-compatibility#launch-window-minor-releases-can-contain-breaking-changes)
for the full policy.
Loading