@vibes.diy/prompts 2.5.15 → 2.5.16
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/llms/fireproof.md +29 -0
- package/package.json +4 -4
package/llms/fireproof.md
CHANGED
|
@@ -521,6 +521,35 @@ export default function App() {
|
|
|
521
521
|
|
|
522
522
|
The pattern: `useVibe().can` gates every write surface — including owner-only management, which the access function enforces via `if (!user.isOwner) throw` so `can.create({ type: "roleGrant", … })` is false for non-owners. `access.hasChannel()` reflects display-only membership, and `isOwner` is a display hint only, never the write gate. The access function is the server-side authority — `useVibe().can` is how the UI reflects its decisions for writes.
|
|
523
523
|
|
|
524
|
+
**Owner-management panels (appoint/revoke moderators, grant/revoke roles) gate on `can.*`, not `isOwner`.** It's tempting to wrap an admin panel in `{isOwner && <ModeratorPanel />}` and have its buttons call `database.put`/`database.del` directly. Don't let `isOwner` be what decides a write — it's the same display hint as everywhere else. Gate each mutating control on the verdict from the doc you'll actually write — appoint on `can.create({ type: "modGrant", role: "moderator", userHandle }).ok`, revoke on `can.delete(grantDoc).ok` — and render `.reason` when denied. `can.*` runs the app's own `access.js` to produce the verdict, so the control's enabled state and message track what the access function decides and stay correct as it grows beyond owner-only (a delegated admin role, say). Gate the panel's *visibility* on those same verdicts too, not `isOwner` alone — otherwise a delegated admin the access function now allows never reaches the controls or their reason.
|
|
525
|
+
|
|
526
|
+
```jsx
|
|
527
|
+
// Don't: isOwner decides visibility AND the writes are ungated — a non-owner the
|
|
528
|
+
// access function would allow never reaches the controls, and isOwner drifts from access.js
|
|
529
|
+
{isOwner && (
|
|
530
|
+
<ModeratorPanel>
|
|
531
|
+
<button onClick={() => database.put({ type: "modGrant", role: "moderator", userHandle })}>Appoint</button>
|
|
532
|
+
<button onClick={() => database.del(grantDoc._id)}>Revoke</button>
|
|
533
|
+
</ModeratorPanel>
|
|
534
|
+
)}
|
|
535
|
+
|
|
536
|
+
// Do: can.* decides visibility AND gates each write, and supplies the denial reason
|
|
537
|
+
const canAppoint = can.create({ type: "modGrant", role: "moderator", userHandle });
|
|
538
|
+
const canRevoke = can.delete(grantDoc);
|
|
539
|
+
{(canAppoint.ok || canRevoke.ok) && (
|
|
540
|
+
<ModeratorPanel>
|
|
541
|
+
{canAppoint.ok && (
|
|
542
|
+
<button onClick={() => database.put({ type: "modGrant", role: "moderator", userHandle })}>Appoint</button>
|
|
543
|
+
)}
|
|
544
|
+
{canRevoke.ok ? (
|
|
545
|
+
<button onClick={() => database.del(grantDoc._id)}>Revoke</button>
|
|
546
|
+
) : (
|
|
547
|
+
<p>{canRevoke.reason}</p>
|
|
548
|
+
)}
|
|
549
|
+
</ModeratorPanel>
|
|
550
|
+
)}
|
|
551
|
+
```
|
|
552
|
+
|
|
524
553
|
### Example: Channel board with open channels (any member posts)
|
|
525
554
|
|
|
526
555
|
Channels everyone can read, and any signed-in user can post to. The channel doc is `grant.public` (read for everyone) and the post rule checks only the author — **no `ctx.requireAccess`**, because public is read-only and would block every non-owner. (For a members-only board where the owner appoints who can post, grant a poster role and `requireAccess` it, as in the announcements example above.) The UI uses `access.hasChannel()` to filter which channels to display, and `useVibe().can` to gate writes.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibes.diy/prompts",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.16",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"description": "",
|
|
@@ -30,9 +30,9 @@
|
|
|
30
30
|
"@fireproof/core-types-base": "~0.24.19",
|
|
31
31
|
"@fireproof/core-types-protocols-cloud": "~0.24.19",
|
|
32
32
|
"@fireproof/use-fireproof": "~0.24.19",
|
|
33
|
-
"@vibes.diy/call-ai-v2": "^2.5.
|
|
34
|
-
"@vibes.diy/identity": "^2.5.
|
|
35
|
-
"@vibes.diy/use-vibes-types": "^2.5.
|
|
33
|
+
"@vibes.diy/call-ai-v2": "^2.5.16",
|
|
34
|
+
"@vibes.diy/identity": "^2.5.16",
|
|
35
|
+
"@vibes.diy/use-vibes-types": "^2.5.16",
|
|
36
36
|
"arktype": "~2.2.1",
|
|
37
37
|
"json-schema-faker": "~0.6.2"
|
|
38
38
|
},
|