Answer product-owner round 1: 0 🔴, 1 🟡 (0 misread); scripts a plugin links stay unversioned until item 43, assetHref listed as reserved, the per-render stat goes to the architect
This commit is contained in:
@@ -246,7 +246,8 @@ Revisit only if the stated reason stops holding.
|
||||
- **`locale` is a host-owned query param** — in `parseListQuery`'s reserved set, so a localized list
|
||||
page doesn't hand a plugin a phantom `locale` filter. The i18n view locals (`t`, `locale`, `locales`,
|
||||
`localeHref`, `localeParam`, `localeSwitch`, `dir`) are likewise reserved, merged after a handler's
|
||||
`data` so a collision loses the key instead of breaking the shell.
|
||||
`data` so a collision loses the key instead of breaking the shell — as is `assetHref`
|
||||
(`src/http/static.ts`), which stays undocumented for plugins because calling it is not yet contract.
|
||||
- **Catalogs are checked at boot, not at render.** Every locale is compared against its set's `en-US`
|
||||
— keys, string-vs-plural kind, and the plural categories `Intl.PluralRules` requires — and a
|
||||
mismatch stops startup. A plugin may ship fewer locales than the host (its strings fall back to
|
||||
|
||||
@@ -511,8 +511,8 @@ export async function listThings(ctx: RequestContext) {
|
||||
`include()` the core building-block partials and its own. To load the plugin's own CSS, pass its
|
||||
`/public/<id>/x.css` href in the shell's `styles` slot — see the reference's `views/shifts.ejs`.
|
||||
The host adds the file's content hash to every `/public/` href the shell renders, so browsers and
|
||||
any cache in front of Plainpages keep it for a year; a `/public/` URL your own markup writes is
|
||||
kept for five minutes, then revalidated.
|
||||
any cache in front of Plainpages keep the file for a year; a `/public/` URL your own markup writes
|
||||
is kept for five minutes, then revalidated.
|
||||
- **Finer authorization than the route `permission`** uses the guards from `@plainpages/plugin-api`:
|
||||
`requireSession(ctx)`, `can(ctx, permission)` (coarse JWT-claim check, zero I/O), and
|
||||
`check(keto, ctx, {namespace, object, relation})` (a live Keto check; anonymous ⇒ denied). Throw
|
||||
@@ -1175,7 +1175,7 @@ Rules worth knowing:
|
||||
edit/new/remove/save`, `filter.*`, `pagination.*`, `table.*` — and a plugin's lookup falls through
|
||||
to them. Keep your catalog for your domain words.
|
||||
- **Reserved view locals:** `t`, `locale`, `locales`, `localeHref`, `localeParam`, `localeSwitch`,
|
||||
`dir`. They are merged after your `data`, so a colliding key of yours is ignored rather than
|
||||
`dir`, and the host-internal `assetHref`. They are merged after your `data`, so a colliding key of yours is ignored rather than
|
||||
breaking the shell. `locale` is likewise reserved in `parseListQuery`, never returned as a filter.
|
||||
|
||||
**Kratos writes the auth flow's own text** (field labels, validation errors), tagging each string
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
`Bar = 1`
|
||||
|
||||
`Next ID = 43`
|
||||
`Next ID = 44`
|
||||
|
||||
## Items
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
| 16 | 0.5.0 | | question | **Decide whether the single Keto `Resource` namespace splits into per-domain namespaces.** | 3 | 2 | 3 | 6 | 6 | 7 by 2 | 0.5 |
|
||||
| 6 | 0.5.0 | | | **Warn at discovery when a route or nav node gates on a permission no plugin declares.** | 2 | 1 | 1 | 2 | 2 | 7 by 3, 9 by 3 | 8.0 |
|
||||
| 23 | 0.5.0 | | | **Give list pages one view-model helper from query to pagination, instead of ~40 hand-written lines each.** | 3 | 1 | 2 | 4 | 5 | 1 by 4, 9 by 2, code health by 3 | 7.9 |
|
||||
| 43 | 0.5.0 | | | **Let a plugin version the scripts and other `/public/` files its own markup links, so they are cached as immutable too.** | 2 | 2 | 1 | 3 | 3 | 8 by 3, 7 by 2 | 5.0 |
|
||||
| 28 | 0.5.0 | | | **Let a plugin add entries to the profile menu through the plugin API.** | 2 | 2 | 2 | 4 | 4 | 7 by 4, 1 by 2 | 4.2 |
|
||||
| 2 | 0.5.0 | | | **Rename the admin example plugin to a name that says what it administers.** | 3 | 1 | 2 | 4 | 6 | 9 by 3, code health by 2 | 2.6 |
|
||||
| 5 | 0.5.0 | | | **List grants that no installed plugin declares, with a remove action.** | 2 | 2 | 2 | 4 | 4 | 2 by 3 | 2.1 |
|
||||
@@ -104,6 +105,15 @@ is ungrantable from the GUI and answers a permanent 403. A warning, not an error
|
||||
Every list screen bridges `parseListQuery`/`paginate` to the partials by hand. At minimum a
|
||||
`buildPaginationModel(page, hrefFor)`. Exported through the barrel, so it is contract surface.
|
||||
|
||||
### 43. Let a plugin version the scripts and other `/public/` files its own markup links, so they are cached as immutable too.
|
||||
|
||||
The host versions every `/public/` href it renders (`src/http/static.ts`): the shell's stylesheets,
|
||||
favicon and logo, and a plugin's `styles`. A file a plugin's own markup links, such as fastjira's
|
||||
`board-drag.js`, keeps an unversioned URL and is revalidated every five minutes. Offering a way —
|
||||
`assetHref` documented as a view local, a `ctx.assetHref`, or a `scripts` slot in the shell — adds to
|
||||
the plugin API, hence a minor. Pick one with the plugin authors' panel, then document it in README →
|
||||
Reserved view locals.
|
||||
|
||||
### 28. Let a plugin add entries to the profile menu through the plugin API.
|
||||
|
||||
The profile dropdown stays a dropdown: Sign out is its only entry today, and it will gain more.
|
||||
|
||||
Reference in New Issue
Block a user