|
| 1 | +--- |
| 2 | +"@objectstack/plugin-email": patch |
| 3 | +"@objectstack/plugin-security": patch |
| 4 | +"@objectstack/plugin-sharing": patch |
| 5 | +"@objectstack/plugin-webhooks": patch |
| 6 | +--- |
| 7 | + |
| 8 | +fix(plugins): a declared item reaches its schema intact — retire the `i?.content ?? i` unwrap from plugin read paths (#8378) |
| 9 | + |
| 10 | +Ten production reads over `SchemaRegistry.listItems` unwrapped every declared |
| 11 | +item as `i?.content ?? i`, presuming a `{ name, content }` storage envelope. |
| 12 | +That envelope has **no producer**. Re-measured at these seams rather than |
| 13 | +inherited from #7519's measurement of `MetadataFacade`: |
| 14 | + |
| 15 | +- `registerMetadataCollections` (objectql) registers each stack-collection |
| 16 | + element as-is — `registerItem(type, item, 'name')`, no boxing; |
| 17 | +- `loadMetaFromDb` registers `convertStoredItem(JSON.parse(record.metadata))` — |
| 18 | + the parsed body, never the `sys_metadata` row (whose body column is |
| 19 | + `metadata`, not `content`); |
| 20 | +- the facade's own interim boxing of non-object values, the one writer that ever |
| 21 | + produced the shape, was removed by #8349. |
| 22 | + |
| 23 | +**Removal is a fix, not a cleanup.** None of the types read through these seams |
| 24 | +— `permission`, `position`, `capability`, `object`, `sharingRule`, `webhook`, |
| 25 | +`emailTemplate` — declares a stored `content` key; every one of them rejects it |
| 26 | +as an unrecognized key. So wherever the key did appear the unwrap replaced a |
| 27 | +whole authoring document with one of its values, and `''` — falsy but |
| 28 | +non-nullish — passed `??` and then died at the reader's own `filter(Boolean)`, |
| 29 | +dropping the item with no warning, no count and no row. |
| 30 | + |
| 31 | +**On email templates the harm was sharpest, and it is the one users will |
| 32 | +notice.** `content` really is a spelling an author can write there: |
| 33 | +`EmailTemplateDefinitionSchema` lists it in its `strictObject` **aliases** table |
| 34 | +(`content: 'bodyHtml'`). That table is a *rejection* facility, not a conversion — |
| 35 | +it feeds `strictUnknownKeyError`, which runs only on the `unrecognized_keys` |
| 36 | +path and only builds a message; nothing rewrites the key, and the ADR-0087 |
| 37 | +conversion layer has no `email_template` entry either. The schema was therefore |
| 38 | +always ready with the author's fix, and the unwrap was the one thing standing |
| 39 | +between the author and it: the HTML string reached |
| 40 | +`EmailTemplateDefinitionSchema.parse()`, which answered `Invalid input: expected |
| 41 | +object, received string`, and the boot warning's `name` field came back |
| 42 | +`undefined` — so an operator could not even tell **which** template had failed. |
| 43 | + |
| 44 | +A template authored with `content` now yields what it was always meant to: |
| 45 | + |
| 46 | +> Unrecognized key(s) on this email template: `content`. Did you mean |
| 47 | +> `content` → `bodyHtml`? |
| 48 | +
|
| 49 | +…named against the template it came from, and counted as `skipped` rather than |
| 50 | +vanishing. |
| 51 | + |
| 52 | +No behaviour changes for spec-valid metadata: the reads hand back exactly the |
| 53 | +documents they always did. |
0 commit comments