Found by the domain:skills dev seat while repairing the ten governed fences of objectui#8335. ⛔ Out of that card's scope — objectui#8335 repairs fences that RE-DECLARE a published type; this is a fence that READS a member the published type no longer has, which is a different defect class. Not touched there, filed here.
The defect
skills/objectui/guides/auth-permissions.md — the PermissionProvider wiring example (section "Permission setup", the fence whose App() renders PermissionProvider) passes:
userRoles={user?.roles || ['viewer']}
AuthUser has had no roles member since objectui#5424 (maintainer ruling 2026-08-22): framework ADR-0090 D3 renamed roles to positions with no deprecation window, and packages/auth/src/types.ts carries a comment forbidding both re-declaring it and re-emitting it as a compatibility shadow. user.roles therefore lands on the type's [key: string]: unknown index signature.
Measured, on b38014e8, against the BUILT surface
Probe compiled with tsc --ignoreConfig --noEmit --strict --moduleResolution bundler against packages/auth/dist/types.d.ts (built through the check:skill-examples package closure). Two lines, one control:
declare const user: AuthUser | null;
const userRoles: string[] = user?.roles || ['viewer']; // line 4
const userPositions: string[] = user?.positions || ['viewer']; // line 5 — the control
Result — exactly one diagnostic, and it is on the guide's line:
__probe_roles.ts(4,7): error TS2740: Type '{}' is missing the following properties from type 'string[]': length, pop, push, concat, and 28 more.
⇒ The guide's line is a compile error for any reader who copies it into a typed app: unknown in the left arm of the truthiness operator narrows to the empty object type, which is not a string array. Line 5 produced no diagnostic, so the instrument was lit and positions is the working spelling.
PermissionProvider's prop is required and typed userRoles: string[] (packages/permissions/src/PermissionProvider.tsx:27), so there is no looser arm for the guide's value to land in.
The runtime half, attributed rather than re-measured
objectui#5424 records that the protocol-17 session face emits no roles key at all (measured live in objectui#5389). If that still holds, a reader who silences the type error gets ['viewer'] for every signed-in user unconditionally — a permission example that grants the narrowest role to everyone while looking wired. ⛔ Whoever takes this should re-measure that half rather than inherit it; only the compile half above was measured here.
Why it survived
The fence is UNMARKED, so check:skill-examples does not compile it, and the guide's own AuthUser fence used to declare roles?: string[] — the copy made the read look correct. objectui#8335 replaced that copy with an import of the published type, which removes the local licence for this line but deliberately leaves the line itself alone.
Suggested repair, for whoever picks it up
Change the read to user?.positions, and decide whether the example fence should carry os:check so the compiler holds it. Both are skills judgements over a GOVERNED surface (skills/**), so the PR is agent-drafts / human-merges.
Filed by Claude Code — see https://claude.ai/code
Found by the
domain:skillsdev seat while repairing the ten governed fences of objectui#8335. ⛔ Out of that card's scope — objectui#8335 repairs fences that RE-DECLARE a published type; this is a fence that READS a member the published type no longer has, which is a different defect class. Not touched there, filed here.The defect
skills/objectui/guides/auth-permissions.md— thePermissionProviderwiring example (section "Permission setup", the fence whoseApp()rendersPermissionProvider) passes:AuthUserhas had norolesmember since objectui#5424 (maintainer ruling 2026-08-22): framework ADR-0090 D3 renamedrolestopositionswith no deprecation window, andpackages/auth/src/types.tscarries a comment forbidding both re-declaring it and re-emitting it as a compatibility shadow.user.rolestherefore lands on the type's[key: string]: unknownindex signature.Measured, on
b38014e8, against the BUILT surfaceProbe compiled with
tsc --ignoreConfig --noEmit --strict --moduleResolution bundleragainstpackages/auth/dist/types.d.ts(built through thecheck:skill-examplespackage closure). Two lines, one control:Result — exactly one diagnostic, and it is on the guide's line:
⇒ The guide's line is a compile error for any reader who copies it into a typed app:
unknownin the left arm of the truthiness operator narrows to the empty object type, which is not a string array. Line 5 produced no diagnostic, so the instrument was lit andpositionsis the working spelling.PermissionProvider's prop is required and typeduserRoles: string[](packages/permissions/src/PermissionProvider.tsx:27), so there is no looser arm for the guide's value to land in.The runtime half, attributed rather than re-measured
objectui#5424 records that the protocol-17 session face emits no
roleskey at all (measured live in objectui#5389). If that still holds, a reader who silences the type error gets['viewer']for every signed-in user unconditionally — a permission example that grants the narrowest role to everyone while looking wired. ⛔ Whoever takes this should re-measure that half rather than inherit it; only the compile half above was measured here.Why it survived
The fence is UNMARKED, so
check:skill-examplesdoes not compile it, and the guide's ownAuthUserfence used to declareroles?: string[]— the copy made the read look correct. objectui#8335 replaced that copy with an import of the published type, which removes the local licence for this line but deliberately leaves the line itself alone.Suggested repair, for whoever picks it up
Change the read to
user?.positions, and decide whether the example fence should carryos:checkso the compiler holds it. Both are skills judgements over a GOVERNED surface (skills/**), so the PR is agent-drafts / human-merges.Filed by Claude Code — see https://claude.ai/code