Skip to content

Commit 3b0b61c

Browse files
os-zhuangclaude
andauthored
fix(metadata): route the three read-side /meta verbs through the canonical type boundary (#9157) (#9191)
* fix(metadata-protocol): route the three read verbs through the canonical /meta type boundary (#9157) auditMetaItem, historyMetaItem and findReferencesToMeta derived their type key from PLURAL_TO_SINGULAR - the manifest-collection map #7894 moved this boundary off - instead of calling canonicalizeMetaRequestType, which nine sibling verbs already call. That call carries both the URL map and metaUrlSpellingRefusal, and the refusal is the half those three could never reach: it lives inside the function they skipped. Step 1 of the #9180 maintainer ruling (the /meta type segment is singular, always). Steps 2 and 3 stay unbundled and independently revertible. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NTKPDRoynY8i3HmdSFUxFj * chore(changeset): record the read-verb canonical /meta type fold (#9157) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NTKPDRoynY8i3HmdSFUxFj --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 62b1427 commit 3b0b61c

3 files changed

Lines changed: 672 additions & 3 deletions

File tree

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
---
2+
"@objectstack/metadata-protocol": patch
3+
---
4+
5+
fix(metadata): the three read-side `/meta` verbs reach the canonical type boundary — history, audit and references (#9157)
6+
7+
<!-- adr-0087: not-required (no-migration-prescription) No authorable key is
8+
added, renamed, retired or tombstoned. This routes three existing protocol
9+
methods through an existing request-boundary function; the only externally
10+
visible movement is on three GET routes, described below. -->
11+
12+
Step ① of the maintainer ruling in #9180 (2026-08-16): **the `/meta` type
13+
segment is singular, always.**
14+
15+
`auditMetaItem`, `historyMetaItem` and `findReferencesToMeta` each opened by
16+
deriving their type key from `PLURAL_TO_SINGULAR` — the MANIFEST-COLLECTION map
17+
that #7894 moved this boundary off — instead of calling
18+
`canonicalizeMetaRequestType`, which the nine sibling `/meta` verbs already
19+
call. That one call carries **both** the URL spelling map **and**
20+
`metaUrlSpellingRefusal`, and the refusal is the half these three could never
21+
reach: it lives *inside* the function they skipped.
22+
23+
**What changes on the wire**, on `GET /api/v1/meta/:type/:name/history`,
24+
`…/audit` and `…/references`:
25+
26+
| caller's `:type` | before | after |
27+
| --- | --- | --- |
28+
| `viewes` — an unrecognised spelling of a **declared** type | 200 with an empty body | **400 `INVALID_REQUEST`**, naming both accepted spellings (`view`, `views`) |
29+
| `translations`, `fields`, `seeds`, `external_catalogs` — recognised plurals of the four types absent from the manifest map | 200 with an empty body | 200 with the **real** rows |
30+
| `views` — a recognised plural already in the manifest map | unchanged | unchanged |
31+
| `fieldz` — reaches for no declared type | unchanged | unchanged; the refusal stays narrow, so a plugin-registered kind can never trip it |
32+
33+
The harm being closed is the empty-accumulator shape: a plural read answered
34+
`{ "events": [] }` / `{ "references": [] }` — read by an operator as *"nothing
35+
depends on this"* — at exactly the moment they were about to rename or delete.
36+
**Loudly wrong beats quietly lying**, so a spelling the platform cannot honour
37+
is now refused with the canonical one named rather than answered emptily.
38+
39+
Two measured details worth stating, because both invert an intuition:
40+
41+
- On `historyMetaItem` the unfolded plural was not merely a wrong key, it was a
42+
door **around** a gate. `field` declares neither `allowOrgOverride` nor
43+
`allowRuntimeCreate`, so the canonical spelling is refused by the overlay gate
44+
and never reaches the store — while `fields` took
45+
`isRuntimeCreateAllowed`'s no-static-registry-entry arm (the plugin path,
46+
permissive by construction) and issued a real `sys_metadata_history` read
47+
keyed `'fields'`. Same empty body, opposite path.
48+
- On `findReferencesToMeta` the refusal is the **whole** visible change. Every
49+
`REFERENCE_PATHS` key is manifest-present and already folded, so a
50+
manifest-absent target still answers `{ "references": [] }` — which that
51+
method documents as a legitimate no-hit. Widening that registry is a coverage
52+
question, not a spelling one.
53+
54+
Recognised plural spellings are **not** retired here — `metaUrlSpellingRefusal`
55+
returns `null` for `views` and for `translations`, and a pin asserts it. That is
56+
#9180 step ③, which the ruling requires to stay independently revertible.

0 commit comments

Comments
 (0)