@ultimat3/admin 22.10.0 → 22.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +26 -0
  2. package/package.json +16 -16
package/README.md CHANGED
@@ -153,6 +153,32 @@ and one reader. A `path` the admin does not declare throws `X_ADMIN_PAGE_PATH_IN
153
153
  paths that would have worked — a page serving an admin URL the admin never built is a screen whose
154
154
  permissions nothing composed.
155
155
 
156
+ ### A refused page answers 403
157
+
158
+ `guardedPage()` renders `AdminPageDenied` in place of the page, and the page's `load` decides the
159
+ status: a mount that resolves the body in `load` answers the refusal with `withStatus` from
160
+ `@ultimat3/render`, asking the same `decideAll` the guard asked. As of 2026-09.
161
+
162
+ ```ts
163
+ import { type AdminApp, type AdminPageProps, adminRouteFor, decideAll } from '@ultimat3/admin';
164
+ import { withStatus } from '@ultimat3/render';
165
+
166
+ declare const admin: AdminApp;
167
+ declare function adminCtxForRequest(): AdminPageProps['ctx'];
168
+
169
+ const route = adminRouteFor(admin, `${admin.basePath}/ops`);
170
+
171
+ // The mount's `load`: the guarded body, and the status the same decision answers.
172
+ export const load = async ({ params, url }: Omit<AdminPageProps, 'ctx'>) => {
173
+ const ctx = adminCtxForRequest();
174
+ const data = { body: route.component === null ? null : await route.component({ ctx, params, url }) };
175
+ return decideAll(ctx.authz, route.permissions, ctx.actor).allowed ? data : withStatus(403, data);
176
+ };
177
+ ```
178
+
179
+ The same page, inside the app's shell, with a 403 (and `noindex`) on the response. `withStatus(404,
180
+ …)` is the answer for a row the page cannot find.
181
+
156
182
  ### Splitting the admin across files
157
183
 
158
184
  `defineAdmin` takes **plain values** — `entities`, `resources`, `actions`, `jobs`, `pages`, `nav`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ultimat3/admin",
3
- "version": "22.10.0",
3
+ "version": "22.12.0",
4
4
  "description": "Two dashboards: the /_x framework dev panels and the generated, AI-first app admin",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -32,20 +32,20 @@
32
32
  "test": "bun test"
33
33
  },
34
34
  "dependencies": {
35
- "@ultimat3/action": "22.10.0",
36
- "@ultimat3/ai": "22.10.0",
37
- "@ultimat3/cache": "22.10.0",
38
- "@ultimat3/core": "22.10.0",
39
- "@ultimat3/db": "22.10.0",
40
- "@ultimat3/entity": "22.10.0",
41
- "@ultimat3/i18n": "22.10.0",
42
- "@ultimat3/jobs": "22.10.0",
43
- "@ultimat3/mcp": "22.10.0",
44
- "@ultimat3/money": "22.10.0",
45
- "@ultimat3/policy": "22.10.0",
46
- "@ultimat3/query": "22.10.0",
47
- "@ultimat3/render": "22.10.0",
48
- "@ultimat3/schema": "22.10.0",
49
- "@ultimat3/ui": "22.10.0"
35
+ "@ultimat3/action": "22.12.0",
36
+ "@ultimat3/ai": "22.12.0",
37
+ "@ultimat3/cache": "22.12.0",
38
+ "@ultimat3/core": "22.12.0",
39
+ "@ultimat3/db": "22.12.0",
40
+ "@ultimat3/entity": "22.12.0",
41
+ "@ultimat3/i18n": "22.12.0",
42
+ "@ultimat3/jobs": "22.12.0",
43
+ "@ultimat3/mcp": "22.12.0",
44
+ "@ultimat3/money": "22.12.0",
45
+ "@ultimat3/policy": "22.12.0",
46
+ "@ultimat3/query": "22.12.0",
47
+ "@ultimat3/render": "22.12.0",
48
+ "@ultimat3/schema": "22.12.0",
49
+ "@ultimat3/ui": "22.12.0"
50
50
  }
51
51
  }