uniweb 0.89.0 → 0.89.1

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uniweb",
3
- "version": "0.89.0",
3
+ "version": "0.89.1",
4
4
  "description": "Create structured Vite + React sites with content/code separation",
5
5
  "type": "module",
6
6
  "bin": {
@@ -41,17 +41,17 @@
41
41
  "js-yaml": "^4.1.0",
42
42
  "prompts": "^2.4.2",
43
43
  "tar": "^7.0.0",
44
- "@uniweb/runtime": "^0.29.5",
45
- "@uniweb/core": "^0.38.0",
44
+ "@uniweb/core": "^0.38.1",
46
45
  "@uniweb/kit": "^0.20.0",
46
+ "@uniweb/runtime": "^0.29.6",
47
+ "@uniweb/semantic-parser": "^1.5.1",
47
48
  "@uniweb/content-writer": "^0.3.4",
48
- "@uniweb/schemas": "^0.13.0",
49
- "@uniweb/semantic-parser": "^1.5.1"
49
+ "@uniweb/schemas": "^0.13.0"
50
50
  },
51
51
  "peerDependencies": {
52
- "@uniweb/content-reader": "^1.2.8",
52
+ "@uniweb/semantic-parser": "^1.5.1",
53
53
  "@uniweb/build": "^0.80.3",
54
- "@uniweb/semantic-parser": "^1.5.1"
54
+ "@uniweb/content-reader": "^1.2.8"
55
55
  },
56
56
  "peerDependenciesMeta": {
57
57
  "@uniweb/build": {
@@ -2510,8 +2510,8 @@ const sessions = entity?.hydrated?.items.filter((item) => item.section === 'sess
2510
2510
  section's fields (`record.brief.name`, not `record.name`), and a record carries **no
2511
2511
  items**. Read one entity for its items. Each item carries `section`, its section's name
2512
2512
  (the word a write takes), and `id`, which is what the writer takes to update, move or
2513
- remove it. `scope: 'mine'` lists only the viewer's own records. Without it, the operator
2514
- also gets everyone else's.
2513
+ remove it. `scope: 'mine'` lists only the viewer's own records; without it, a list also
2514
+ holds what was shared with the viewer.
2515
2515
 
2516
2516
  ⭐ **`absent` and an empty `ready` are different answers, and confusing them is the
2517
2517
  mistake to avoid.** `absent` = there is no live source (no `backend` service, or nobody signed
@@ -2543,10 +2543,12 @@ await writer.remove(itemId)
2543
2543
 
2544
2544
  ### ⛔ Permissions are the SERVER'S, and your UI is only a courtesy
2545
2545
 
2546
- Gate your controls on what the viewer may do — `viewer.roles` (the site's operator
2547
- holds `system_admin`), or a record's own `can_edit` from a single-entity read — but
2548
- **never rely on that for safety**. A foundation runs with exactly the viewer's own
2549
- authority, so hiding a button hides a button.
2546
+ Gate your controls on what the viewer may do — a record's own `can_edit` from a
2547
+ single-entity read — but **never rely on that for safety**. A foundation runs with
2548
+ exactly the viewer's own authority, so hiding a button hides a button. ⛔ **Not on
2549
+ `viewer.roles`:** a session signed in on a site holds a member's rights — the operator's
2550
+ too — so its roles never name an administrator, and a gate on `system_admin` shows the
2551
+ operator nothing.
2550
2552
 
2551
2553
  What protects content is the **entry**: a member writes their own entries and not
2552
2554
  another's, and the store enforces it. **Models are open** — anyone signed in may
@@ -2565,6 +2567,19 @@ sections:
2565
2567
  `append_only` holds against the item's own author. That is the difference between a
2566
2568
  permission model and a CSS one.
2567
2569
 
2570
+ ### The Admin link
2571
+
2572
+ ```jsx
2573
+ const { adminHref } = useSession()
2574
+ {adminHref && <a href={adminHref}>Admin</a>}
2575
+ ```
2576
+
2577
+ `adminHref` is set only for a signed-in account the backend's administration admits —
2578
+ the operator, and whoever else administers it — and is `null` for everyone else. It
2579
+ takes them there already signed in. ⛔ **Navigate to it, never `fetch` it**: the answer is
2580
+ a redirect carrying a one-time credential no script on the site is to hold. It decides
2581
+ what to offer, not what is allowed — on the site the operator acts as a member.
2582
+
2568
2583
  ### A backend on your machine
2569
2584
 
2570
2585
  You do not need a live backend to build against one. In `site.yml`:
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "generatedAt": "2026-10-09T22:44:36.037Z",
3
+ "generatedAt": "2026-10-11T15:34:07.453Z",
4
4
  "packages": {
5
5
  "@uniweb/api": {
6
- "version": "0.7.0"
6
+ "version": "0.8.0"
7
7
  },
8
8
  "@uniweb/build": {
9
9
  "version": "0.80.3"
@@ -15,7 +15,7 @@
15
15
  "version": "0.3.4"
16
16
  },
17
17
  "@uniweb/core": {
18
- "version": "0.38.0"
18
+ "version": "0.38.1"
19
19
  },
20
20
  "@uniweb/frame-bridge": {
21
21
  "version": "0.3.2"
@@ -36,7 +36,7 @@
36
36
  "version": "0.7.15"
37
37
  },
38
38
  "@uniweb/runtime": {
39
- "version": "0.29.5"
39
+ "version": "0.29.6"
40
40
  },
41
41
  "@uniweb/scene": {
42
42
  "version": "0.1.3"
@@ -54,7 +54,7 @@
54
54
  "version": "0.1.2"
55
55
  },
56
56
  "@uniweb/templates": {
57
- "version": "0.18.7"
57
+ "version": "0.18.8"
58
58
  },
59
59
  "@uniweb/theming": {
60
60
  "version": "0.2.0"