Observation-class finding, surfaced while wiring @object-ui/permissions' tests into tsc for #4040 (tranche 1, PR #4287). Nothing a user meets today — filed rather than fixed because resolving it either way changes a public exported type.
What
packages/types/src/permissions.ts:38:
exportinterfaceRoleDefinition{name: string;label: string;description?: string;inherits?: string[];system?: boolean;permissions: ObjectLevelPermission[];// required}permissions is the only required member besides name and label, and it is documented as the role's direct object-level grants.
Nothing in this repository reads it. A repo-wide search for role.permissions / roleDef.permissions / r.permissions over packages/** and apps/** (excluding dist and node_modules) returns nothing. The four places that take a RoleDefinition[] all use name and inherits only:
packages/permissions/src/evaluator.ts:18, and resolveRoles at :92 — walks inherits, matches on namepackages/permissions/src/store.ts:34packages/permissions/src/PermissionProvider.tsx:22
Every grant the evaluator actually applies comes from the separate ObjectPermissionConfig[], keyed by object with a roles map inside it. So there are two declared homes for "what a role may do", and only one of them is wired.
How it surfaced
Five of @object-ui/permissions' declared TEST_DEBT errors were TS2741 — fixtures annotated RoleDefinition that omit permissions:
src/__tests__/evaluator.test.ts(16,7): error TS2741: Property 'permissions' is missing in type '{ name: string; label: string; }' but required in type 'RoleDefinition'.
src/__tests__/store.test.ts(14,3): error TS2741: ...
PR #4287 gives each fixture permissions: [], which is accurate for those roles and leaves the type alone. That is the right fix for the test files, and it is also the thing that makes the dormancy visible: five fixtures independently omitted a required field, and every case still asserted exactly what its author meant, because no code path was ever going to look.
Why it is finding and not queued
No user-visible behaviour depends on it either way. It is one of two shapes, and telling them apart is a product question, not a code one:
- The field is aspirational — role-attached grants were designed and never wired. Then it is ADR-0049 enforce-or-remove territory: either build the reader or retire the declaration.
- The field is intended and merely optional in practice — every real role today gets its grants from
ObjectPermissionConfig. Then it should be permissions?:, and the required-ness is what is wrong.
Either resolution edits packages/types' published surface, so it wants a ruling rather than a guess. Cheap to settle whenever the permissions surface next gets attention.
Refs #4040, #4287, objectstack-ai/objectstack#4118.
Observation-class finding, surfaced while wiring
@object-ui/permissions' tests intotscfor #4040 (tranche 1, PR #4287). Nothing a user meets today — filed rather than fixed because resolving it either way changes a public exported type.What
packages/types/src/permissions.ts:38:permissionsis the only required member besidesnameandlabel, and it is documented as the role's direct object-level grants.Nothing in this repository reads it. A repo-wide search for
role.permissions/roleDef.permissions/r.permissionsoverpackages/**andapps/**(excludingdistandnode_modules) returns nothing. The four places that take aRoleDefinition[]all usenameandinheritsonly:packages/permissions/src/evaluator.ts:18, andresolveRolesat:92— walksinherits, matches onnamepackages/permissions/src/store.ts:34packages/permissions/src/PermissionProvider.tsx:22Every grant the evaluator actually applies comes from the separate
ObjectPermissionConfig[], keyed by object with arolesmap inside it. So there are two declared homes for "what a role may do", and only one of them is wired.How it surfaced
Five of
@object-ui/permissions' declaredTEST_DEBTerrors wereTS2741— fixtures annotatedRoleDefinitionthat omitpermissions:PR #4287 gives each fixture
permissions: [], which is accurate for those roles and leaves the type alone. That is the right fix for the test files, and it is also the thing that makes the dormancy visible: five fixtures independently omitted a required field, and every case still asserted exactly what its author meant, because no code path was ever going to look.Why it is
findingand not queuedNo user-visible behaviour depends on it either way. It is one of two shapes, and telling them apart is a product question, not a code one:
ObjectPermissionConfig. Then it should bepermissions?:, and the required-ness is what is wrong.Either resolution edits
packages/types' published surface, so it wants a ruling rather than a guess. Cheap to settle whenever the permissions surface next gets attention.Refs #4040, #4287, objectstack-ai/objectstack#4118.