Skip to content

Commit e1e9022

Browse files
docs(releases): fold #25563, #25564, #25565 and #25560 into the 18.1.0 notes (#25590)
<!-- claude-projects-attribution: {"github_login":"marchtian"} --> _Requested by **田騏** · [project thread](https://claude.ai/code/project/chan_01VmuUhXU9SSUzqJYyXSmYSi?thread=cmsg_01VmuUhXU9SSUzqJYyXSmYSiRwWtsarkLPmw9fMYiFZ3LY)_ ## Summary Five more changesets reached `main` after #25562 was compiled at `03243fc637`, still before the 18.1.0 cut. This PR folds them into the 18.1.0 notes. It is docs-only. Three are breaking patches: - **#25563, auth secret**: the temporary auth secret is now used on a development or test boot only. This goes under "Boot and deployment", and checklist step 2 now names the embedded-kernel case. - **#25563, window functions**: `findWithWindowFunctions()` now serves a closed set of functions and directions. This goes under "Datasources and drivers". - **#25565**: a REST credential is honoured only in the environment that validated it. This goes under "REST, MCP and API clients", and checklist step 4 covers multi-environment hosts. The other two: - **#25564** is semantic: it records the change of meaning that #25483 made to `runAs`. It goes under "Semantic changes". - **#25560** is a fix and is counted under other fixes. The counts are now 258 entries, split 81 / 9 / 47 / 3 / 118. 90 changesets are declared breaking, 48 `minor` and 42 `patch`, and `check-adr-0087-registration --list` reports 90 of 90. The count is updated on the 18.1 page, the v18 index, the releases index and Backward Compatibility. ## Checks These pass locally: `check:role-word`, `check:release-notes`, `check:release-page-status`, `check:release-index-currency-sync`, `check:doc-anchors`, `check:docs-audit-scope`, `check:docs-single-h1`, and an MDX compile of the page. Clause-②: no Metadata-protocol: none 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01At7xrR4rgknXtej5ZkMJHd Co-authored-by: Claude <noreply@anthropic.com>
1 parent 0951a00 commit e1e9022

4 files changed

Lines changed: 48 additions & 13 deletions

File tree

‎content/docs/protocol/backward-compatibility.mdx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ ObjectStack follows strict backward compatibility guarantees to ensure predictab
1919

2020
**The v18 line has exited prerelease mode.** While Changesets was in pre mode with the tag `next`, every release cut from `main` was the next `18.0.0-next.N` on npm's `next` tag, and `scripts/check-changeset-no-major.mjs` stood aside in pre mode, so a pull request could declare a major bump. Changesets has exited pre mode, so the line's GA version is `18.0.0`, which publishes to npm's `latest` tag, and the guard again fails a pull request that declares a `major` bump. See [how a breaking stage lands on the v18 line](/docs/releases/v18#how-a-breaking-stage-lands-on-this-line).
2121

22-
**After 18.0.0, a breaking change ships in a MINOR or a PATCH release.** The maintainer's 2026-10-21 ruling ([#25105](https://github.com/objectstack-ai/objectstack/issues/25105)) keeps the no-major guard and grades each change by the metadata protocol: a key, value or metadata type added, narrowed or given a new meaning takes MINOR, and every other change takes PATCH, breaking or not. A non-protocol breaking change (a REST response, a boot refusal, a CLI exit status, a removed runtime export) keeps its `**BREAKING**` banner and ships as a PATCH. 18.1.0, the first release under the rule, is a MINOR that carries 87 changesets declared breaking.
22+
**After 18.0.0, a breaking change ships in a MINOR or a PATCH release.** The maintainer's 2026-10-21 ruling ([#25105](https://github.com/objectstack-ai/objectstack/issues/25105)) keeps the no-major guard and grades each change by the metadata protocol: a key, value or metadata type added, narrowed or given a new meaning takes MINOR, and every other change takes PATCH, breaking or not. A non-protocol breaking change (a REST response, a boot refusal, a CLI exit status, a removed runtime export) keeps its `**BREAKING**` banner and ships as a PATCH. 18.1.0, the first release under the rule, is a MINOR that carries 90 changesets declared breaking.
2323
</Callout>
2424

2525
ObjectStack follows [Semantic Versioning 2.0.0](https://semver.org/) (`MAJOR.MINOR.PATCH`). The table below describes what each component means; which version a breaking change ships in depends on the line, as the callout above says.

‎content/docs/releases/index.mdx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ meaning takes `minor`, and every other change takes `patch` — a REST door, a
7272
driver, a boot refusal, the CLI or the Console — breaking or not. A
7373
non-protocol breaking change keeps its `**BREAKING**` banner and its ADR-0087
7474
disposition. 18.1.0 is the first release cut under the rule: a minor carrying
75-
87 changesets declared breaking, 39 of them graded `patch`.
75+
90 changesets declared breaking, 42 of them graded `patch`.
7676

7777
What that means when you read a version number:
7878

‎content/docs/releases/v18/18-1.mdx‎

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,22 @@ description: "Release notes and upgrade checklist for 18.1.0, the first minor of
55

66
<Callout type="warn">
77
**How this page was compiled.** From the 18.1.0 changesets on `main` at
8-
`03243fc637` (2026-10-24), before the 18.1.0 cut: a rehearsed
8+
`ba9e0c3749` (2026-10-24), before the 18.1.0 cut: a rehearsed
99
`pnpm run version` in a throwaway clone at `b2c0752900` (73 packages move to
10-
18.1.0, and their `## 18.1.0` sections held 227 distinct entries), and the 26
11-
changesets merged after it, graded the same way. That makes **253 distinct
10+
18.1.0, and their `## 18.1.0` sections held 227 distinct entries), and the 31
11+
changesets merged after it, graded the same way. That makes **258 distinct
1212
entries**. The five sections below use the grouping the GitHub Release body
13-
uses, and the counts are that grouping's: **78** need you to act, **9** are
14-
converted for you, **47** add capabilities, **2** declare a semantic change,
15-
and **117** are other fixes. Nothing here was
13+
uses, and the counts are that grouping's: **81** need you to act, **9** are
14+
converted for you, **47** add capabilities, **3** declare a semantic change,
15+
and **118** are other fixes. Nothing here was
1616
read off a published 18.1.0 package or walked on an upgrade yet: every refusal
1717
is described as its changeset describes it. Anything that lands on `main` before
1818
the cut is in the CHANGELOG and not on this page.
1919
</Callout>
2020

2121
## Highlights — 18.1.0
2222

23-
- ⚠️ **A minor that breaks.** 18.1.0 is a minor version, and 87 of its
23+
- ⚠️ **A minor that breaks.** 18.1.0 is a minor version, and 90 of its
2424
changesets are declared breaking. Under the level rule the maintainer ruled
2525
on 2026-10-21 (#25105, "ruling A"), the v18 line takes no further major: a
2626
change to the metadata protocol takes `minor`, and every other change takes
@@ -88,7 +88,7 @@ else:
8888
| Everything else: REST, drivers, services, the CLI, the Console, `feat:` and `fix!:` alike | `patch` |
8989

9090
So a **patch** release can break a REST client, a boot or a deployment
91-
script, and 18.1.0 carries 39 changesets graded `patch` that say **BREAKING**,
91+
script, and 18.1.0 carries 42 changesets graded `patch` that say **BREAKING**,
9292
beside 48 graded `minor` ones. Pin exact `@objectstack/*` versions, and read the
9393
release notes for every version you cross. Each entry in a CHANGELOG states its
9494
kind on its own `Metadata-protocol:` line, and the GitHub Release body groups the
@@ -102,7 +102,7 @@ you change them.
102102

103103
### Breaking changes you must act on
104104

105-
The 78 entries that are breaking and have no ADR-0087 conversion, and one boot
105+
The 81 entries that are breaking and have no ADR-0087 conversion, and one boot
106106
refusal (`db1c7cc`) that its changeset declares as an addition. Each line names
107107
the one fix; the CHANGELOG entry carries the full FROM → TO.
108108

@@ -116,6 +116,14 @@ the one fix; the CHANGELOG entry carries the full FROM → TO.
116116
is too. Fix: set `OS_AUTH_SECRET`, and enable auth on a stack that mounts
117117
none. A development boot (`os dev`, `--dev`) and an embedded kernel are not
118118
affected.
119+
- **A boot with no `OS_AUTH_SECRET` uses the temporary secret on a development
120+
boot only** (`6abee03`, #25563). It used it whenever `NODE_ENV` was anything
121+
but exactly `production` (unset, `staging`, a typo); now any boot other than
122+
`NODE_ENV=development` or `test` throws `OS_AUTH_SECRET is required outside
123+
development`. `os serve` and `os start` already default an unset `NODE_ENV`
124+
to `production`, so CLI boots behave as before: an embedder that builds its
125+
own kernel is the one that meets it. Fix: set `OS_AUTH_SECRET`, or
126+
`NODE_ENV=development` for a local boot.
119127
- **A production `os serve` whose `@objectstack/plugin-auth` fails to load is
120128
refused, naming the load error** (`b2e964f`, #25231), `os start` included.
121129
18.0.0 booted it without auth, silently or with one
@@ -253,6 +261,14 @@ door (`422 INVALID_METADATA`), where 18.0.0 accepted it.
253261
starts empty, and a read-only boot no longer opens an empty in-memory database
254262
over a file it cannot open or create (`4d99158`, #25007). Fix: restore from a
255263
backup, or move the file aside yourself; an absent file is created empty.
264+
- **`SqlDriver.findWithWindowFunctions()` serves a closed set** (`6abee03`,
265+
#25563), and so do `driver-sqlite-wasm` and `driver-turso`'s local and
266+
replica transports: the function is one of `row_number`, `rank`,
267+
`dense_rank`, `percent_rank` or `cume_dist`, the direction `asc` or `desc`,
268+
and every `partitionBy` / `orderBy` field is quoted as a column. Anything
269+
else answers `400 INVALID_QUERY`. Fix: use one of those; send a window that
270+
takes an argument (`lag`, `lead`, `ntile`) through `execute()` with bound
271+
parameters.
256272
- **On PostgreSQL, `introspectSchema` reads each table in its own schema**, and
257273
refuses a `search_path` that reaches one table name in two schemas (`74fcec1`,
258274
#24920). Fix: point the connection at one schema.
@@ -302,6 +318,16 @@ door (`422 INVALID_METADATA`), where 18.0.0 accepted it.
302318
naming the parameter (`17f3c65`, #25260), and the published list-query
303319
schemas declare it a non-negative integer (`5f30f00`, #25300). Fix: send a
304320
whole count of zero or more, or leave it out.
321+
- **A credential is honoured only in the environment whose auth service
322+
validated it** (`1361a5a`, #25565), on every route behind the shared REST
323+
auth gate: crud, actions, import and export, batch, sharing, approvals,
324+
analytics, search and security, scoped and unscoped. Before, an environment
325+
with no `auth` service of its own fell back to the default environment's.
326+
A mismatch now answers the same `401` as an unauthenticated request. Only a
327+
multi-environment host whose per-environment kernels carry no `auth`
328+
service meets it; a single-kernel deployment is unchanged. Fix: give each
329+
environment's kernel its own `auth` service, and sign in to the environment
330+
you call.
305331
- **`GET {base}/docs`, the OpenAPI HTML viewer page, is retired**
306332
(`1b3b65e`, #25124). `GET {base}/openapi.json` stays: point your own viewer
307333
at it.
@@ -472,6 +498,12 @@ rows.
472498
`controlled_by_parent` detail follows its master. Nothing changes for a
473499
principal that does not hold the `external` grade, and no earlier release
474500
shipped it.
501+
- **`FlowSchema.runAs` now says what a `system` run may not write**
502+
(`025f6de`, #25564): its description names the refused writes to the four
503+
identity-assignment objects (above, under security), and ADR-0087 D3 records
504+
the change of meaning as `flow-run-as-system-identity-assignment-write-refused`,
505+
so `os migrate meta` lists it for a flow that wrote those rows. It carries no
506+
conversion, and every flow parses as before.
475507

476508
A change of meaning that also breaks is listed with the breaking changes above.
477509

@@ -585,7 +617,8 @@ reinstall.
585617
#### 2. Before the first boot
586618

587619
- Production `os serve` or `os start`: set `OS_AUTH_SECRET`, and do not rely on
588-
`--no-server` or `OS_MIGRATE_AND_EXIT=1` to boot without it.
620+
`--no-server` or `OS_MIGRATE_AND_EXIT=1` to boot without it. A kernel you
621+
embed needs it too, unless it boots with `NODE_ENV=development` or `test`.
589622
- A stack that mounts no auth (`auth` tier off, `--preset minimal`) fails a
590623
production boot: enable auth.
591624
- CORS: list every cross-origin front-end in `OS_CORS_ORIGIN`, loopback origins
@@ -628,3 +661,5 @@ managed datasource.
628661
assignments, invitations or memberships, and move it to `runAs: 'user'` or
629662
the organization endpoints.
630663
- Read the boot's upgrade impact report beside the access upgrade report.
664+
- On a multi-environment host, give each environment's kernel its own `auth`
665+
service before callers reach it, or they get `401`.

‎content/docs/releases/v18/index.mdx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ Each release below is a self-contained page: what it changed, what breaks, and
135135
its own upgrade checklist.
136136

137137
- **[18.1.0](/docs/releases/v18/18-1)** — the first minor, and a minor that
138-
breaks: 87 of its changesets are declared breaking (ruling A grades a
138+
breaks: 90 of its changesets are declared breaking (ruling A grades a
139139
non-protocol breaking change `patch` and a protocol narrowing `minor`). Its
140140
[upgrade checklist](/docs/releases/v18/18-1#upgrade-checklist) moves an
141141
18.0.0 app to 18.1.0; it was compiled from the changesets before the cut and

0 commit comments

Comments
 (0)