From 48d3d2b6096664bc50cdbe56ff42a25e4af0f216 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 19 Sep 2026 04:23:34 +0000 Subject: [PATCH] docs(skills): gate the usePermissions example on can(), a boolean, and mark its fence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `usePermissions` hook example in `skills/objectui/guides/auth-permissions.md` gated two buttons on `check('contacts', 'update', contact)`. `check` answers a `PermissionCheckResult` object, an object is truthy, and so both buttons rendered for every user, denied ones included. The fence was unmarked, so `check-skill-examples` never compiled it. The example now gates on `can('contacts', 'update')` / `can('contacts', 'delete')` — the one boolean spelling the guide's neighbouring paragraph already publishes — annotated `: boolean` so a `check(...)` put back in that position fails to compile. The record argument is dropped: measured against the built `@object-ui/permissions` dist with a throwing Proxy as the record, `evaluatePermission` performs zero property reads on it, and `can()` agrees with `check(..., record).allowed` on every (role, action) of the guide's own config. The fence carries the `os:check` marker and is tagged `tsx`, imports `Button` from `@object-ui/components`, and types `contact` inline, so the gate compiles it against the built dist from now on (Semantic phase: 16 of 16 ts fences). Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01W5y9kRg1YtYaMQYExVLRc2 --- skills/objectui/guides/auth-permissions.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/skills/objectui/guides/auth-permissions.md b/skills/objectui/guides/auth-permissions.md index 71b599f6a3..b9f4672f6a 100644 --- a/skills/objectui/guides/auth-permissions.md +++ b/skills/objectui/guides/auth-permissions.md @@ -221,14 +221,20 @@ guide does not govern it; the two look alike and are unrelated. ### usePermissions hook -```typescript + +```tsx import { usePermissions } from '@object-ui/permissions'; +import { Button } from '@object-ui/components'; -function ContactActions({ contact }) { - const { check, checkField, getFieldPermissions, getRowFilter } = usePermissions(); +function ContactActions({ contact }: { contact: { salary?: number } }) { + const { can, checkField, getFieldPermissions, getRowFilter } = usePermissions(); - const canEdit = check('contacts', 'update', contact); - const canDelete = check('contacts', 'delete', contact); + // Gate on `can`, which answers a boolean. `check` answers `{ allowed, … }`, and + // an object is truthy, so gated on it both buttons render for a denied user + // too; its `record` argument reads no field of the record, so none is passed. + // `: boolean` is what makes a `check(...)` here fail to compile. + const canEdit: boolean = can('contacts', 'update'); + const canDelete: boolean = can('contacts', 'delete'); const canSeeSalary = checkField('contacts', 'salary', 'read'); return (