|
| 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