Found while implementing #10318 / #10327 (permission-set assignment + naming the permissions stack key). Filed unassigned and unlabelled for triage — not fixed in PR #10402, which is scoped to the permission-set surface.
The gap
Measured on origin/main at be9dfe8e5, over the whole published bundle:
grep -rn "definePosition" skills/ → 0 hits
grep -rn "sys_position\b" skills/ → 0 hits
grep -rn "sys_user_position" skills/ → 0 hits
Meanwhile:
positions is enumerated as a top-level defineStack key in skills/objectstack-platform/SKILL.md:180, so an author is told the collection exists.
definePosition is a published export: packages/spec/src/index.ts:116 exports definePosition, EVERYONE_POSITION, GUEST_POSITION, AUDIENCE_ANCHOR_POSITIONS from identity/position.zod.
- Positions are the distribution primitive of the ADR-0090 D3 vocabulary (capability = permission set, distribution = position, hierarchy = business unit) — the axis the reserved-word ratchet (
check:role-word) exists to steer authors onto.
- The resolver treats them as first-class:
packages/core/src/security/resolve-authz-context.ts §5b/§6a resolves position-bound permission sets via sys_position_permission_set, drops sets held through a deactivated position, and gives every authenticated principal an implicit everyone position.
So the bundle names the key, the spec exports the factory, the runtime enforces it — and no skill tells an author how to declare a position, bind a permission set to it, or assign one to a user.
Why this is the same class as #10318 / #10327, on a different surface
Those two were about permission sets: one about naming the registration key, one about the assignment path being undocumented. Positions have both halves missing at once, and they are the scalable grant path — per-user direct grants are the exception, position bindings are how a real deployment distributes capability. An author who reads the bundle end to end today can only reach the per-user path.
Note this is a coverage gap, not stale text: nothing in the bundle says anything wrong about positions. It says nothing at all.
Suggested landing (hint for triage, not a routing decision)
skills/objectstack-data security section is where permission sets already live, and PR #10402 added the assignment how-to there; a positions subsection would sit naturally next to it. Sources to ground it in: packages/spec/src/identity/position.zod.ts, plugin-security/src/objects/sys-user-position.object.ts, plugin-security/src/bootstrap-declared-positions, and resolve-authz-context.ts §5b/§6a for the resolution semantics (deactivated positions, the everyone / guest audience anchors, which cannot be assigned explicitly per ADR-0090 D9).
Whoever picks this up: skills/** is a governed surface (draft PR, human merge), and skills/objectstack-data/SKILL.md is on the check:role-word baseline at a fixed count, so new prose must avoid the reserved word entirely.
Found while implementing #10318 / #10327 (permission-set assignment + naming the
permissionsstack key). Filed unassigned and unlabelled for triage — not fixed in PR #10402, which is scoped to the permission-set surface.The gap
Measured on
origin/mainatbe9dfe8e5, over the whole published bundle:Meanwhile:
positionsis enumerated as a top-leveldefineStackkey inskills/objectstack-platform/SKILL.md:180, so an author is told the collection exists.definePositionis a published export:packages/spec/src/index.ts:116exportsdefinePosition,EVERYONE_POSITION,GUEST_POSITION,AUDIENCE_ANCHOR_POSITIONSfromidentity/position.zod.check:role-word) exists to steer authors onto.packages/core/src/security/resolve-authz-context.ts§5b/§6a resolves position-bound permission sets viasys_position_permission_set, drops sets held through a deactivated position, and gives every authenticated principal an impliciteveryoneposition.So the bundle names the key, the spec exports the factory, the runtime enforces it — and no skill tells an author how to declare a position, bind a permission set to it, or assign one to a user.
Why this is the same class as #10318 / #10327, on a different surface
Those two were about permission sets: one about naming the registration key, one about the assignment path being undocumented. Positions have both halves missing at once, and they are the scalable grant path — per-user direct grants are the exception, position bindings are how a real deployment distributes capability. An author who reads the bundle end to end today can only reach the per-user path.
Note this is a coverage gap, not stale text: nothing in the bundle says anything wrong about positions. It says nothing at all.
Suggested landing (hint for triage, not a routing decision)
skills/objectstack-datasecurity section is where permission sets already live, and PR #10402 added the assignment how-to there; a positions subsection would sit naturally next to it. Sources to ground it in:packages/spec/src/identity/position.zod.ts,plugin-security/src/objects/sys-user-position.object.ts,plugin-security/src/bootstrap-declared-positions, andresolve-authz-context.ts§5b/§6a for the resolution semantics (deactivated positions, theeveryone/guestaudience anchors, which cannot be assigned explicitly per ADR-0090 D9).Whoever picks this up:
skills/**is a governed surface (draft PR, human merge), andskills/objectstack-data/SKILL.mdis on thecheck:role-wordbaseline at a fixed count, so new prose must avoid the reserved word entirely.