Skip to content

Commit ffdc9a5

Browse files
committed
chore: changeset for the ?version= scope on GET /packages/:id (#17416)
Claude-Session: https://claude.ai/code/session_01TSf4DV7ziu4V5j73e46b7c Co-authored-by: Claude <noreply@anthropic.com>
1 parent a15dbd9 commit ffdc9a5

1 file changed

Lines changed: 51 additions & 0 deletions

File tree

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
---
2+
'@objectstack/runtime': minor
3+
---
4+
5+
fix(runtime): `GET /api/v1/packages/:id` honours `?version=` instead of silently ignoring it (#17416)
6+
7+
The route accepted a `?version=` query parameter and the only surface serving it
8+
never read the parameter. A caller asking for a version that is not installed
9+
was answered `200` with the **installed** row, and nothing in the status,
10+
headers or body distinguished that from a version-scoped read that actually
11+
happened.
12+
13+
The parameter is not hypothetical traffic: `ScopedEnvironmentClient.packages.get`
14+
(`@objectstack/client`) declares `version?: string` and appends it, so the SDK
15+
has been sending a parameter the runtime dropped. The handler that honoured it
16+
— the REST registrar's twin of this route — was removed with the duplicate
17+
response shape, and the dispatcher's `/packages` domain never had that read to
18+
inherit.
19+
20+
```
21+
FROM GET /api/v1/packages/com.acme.crm?version=99.0.0 (1.0.0 installed)
22+
-> 200 { data: { manifest: { version: "1.0.0" }, … } }
23+
24+
TO GET /api/v1/packages/com.acme.crm?version=99.0.0
25+
-> 404 { error: { message: "Package 'com.acme.crm' version '99.0.0' not
26+
found — installed version is '1.0.0'" } }
27+
```
28+
29+
**What does not change.** The unversioned read is untouched, down to the row and
30+
the writability verdict it stamps — pinned as the lit control beside the new
31+
assertions, because a green on only the scoped path would also pass with the
32+
ordinary read broken. `?version=` naming the installed version is served
33+
exactly as the unversioned read is, and so is `?version=latest`: the deleted
34+
handler read `requested.value || 'latest'` and its store resolved `latest` to
35+
the newest row, so "no version" and "`latest`" named one request there and name
36+
one request here. An id the registry does not hold keeps its existing 404
37+
wording whether or not `?version=` rode along — a package that is not installed
38+
cannot be at the wrong version.
39+
40+
**This is request-side only.** The response shape is not touched, so the route
41+
still answers with exactly one body shape; comparison is exact string equality
42+
on the version, the same predicate the durable package store uses (`AND version
43+
= ?`), so the two answers to "is this package at version v" cannot drift into
44+
semver-range semantics at one of them.
45+
46+
A repeated `?version=a&version=b` is no longer resolved by silently choosing
47+
one — it is answered with a refusal naming what was seen. The repo's one rule
48+
for a repeated single-valued parameter answers `400 VALIDATION_ERROR` and is
49+
the right end state for this door too; it is not restated here, because the
50+
helper that owns that rule and its message is not exported from
51+
`@objectstack/rest`.

0 commit comments

Comments
 (0)