|
| 1 | +--- |
| 2 | +'@objectstack/rest': patch |
| 3 | +--- |
| 4 | + |
| 5 | +fix(rest): `GET /meta/app` leaves out a `type: 'doc'` navigation entry the caller may not read (#19790) |
| 6 | + |
| 7 | +`DocNavItemSchema` declares that a `doc` entry the member may not read is not |
| 8 | +rendered, and that a `book` entry is not rendered for a member with no readable |
| 9 | +page in it. Until now only a renderer could honour that. The server's app-nav |
| 10 | +filter pruned on `requiredPermissions`, `requiresService` and object servability, |
| 11 | +so every member of the app got the entry. That included its label and the gated |
| 12 | +book or doc name, however the book was gated. |
| 13 | + |
| 14 | +The filter now applies the docs audience (ADR-0046 §6.7) on both the list route |
| 15 | +(`GET /meta/app`) and the by-name route (`GET /meta/app/:name`), in the top-level |
| 16 | +navigation, inside `children` and inside `areas[].navigation`: |
| 17 | + |
| 18 | +- **`doc`**: the entry is dropped when the doc's effective audience does not |
| 19 | + admit the caller. This is the answer `GET /meta/doc/:name` gives. |
| 20 | +- **`book`**: the entry is dropped when the book's own audience does not admit |
| 21 | + the caller, or when none of its pages is readable. A book's pages are the docs |
| 22 | + its groups claim. The *Uncategorized* group that the book tree adds does not |
| 23 | + count. |
| 24 | +- **`book` + `doc`**: the entry is dropped when either of those checks fails. |
| 25 | +- An app emptied by the prune is still served, as it is today when |
| 26 | + `requiredPermissions` empties one. An emptied `group` or area collapses, as |
| 27 | + with every other gate. |
| 28 | + |
| 29 | +The verdicts come from the same resolution that `/meta/doc`, `/meta/doc/:name`, |
| 30 | +`/meta/book` and `/meta/book/:name/tree` now share. What those reads return is |
| 31 | +unchanged. |
| 32 | + |
| 33 | +**Fails closed.** If the book or doc list read throws while `/meta/app` is being |
| 34 | +answered, every `doc` entry is left out of that one response and a warning is |
| 35 | +logged. The rest of the navigation is still served. If the caller's |
| 36 | +permission-set holdings cannot be resolved, set-gated entries are dropped, as |
| 37 | +set-gated content already is. |
| 38 | + |
| 39 | +**Cost.** An app list with no `doc` entry performs no extra read. Otherwise each |
| 40 | +request adds one `book` list read, one permission-set resolution when some book |
| 41 | +is set-gated, and one `doc` list read when a set-gated book exists or an entry |
| 42 | +names only a book. Each of these happens once per request, however many apps are |
| 43 | +listed. Nothing is cached across requests. |
0 commit comments