Skip to content

Entitlements: Kind on the entitlement reference, provider Kind validation (#289) - #351

Merged
blindzero merged 7 commits into
mainfrom
feature/289-entitlement-kind
Nov 1, 2026
Merged

blindzero merged 7 commits into
mainfrom
feature/289-entitlement-kind

Conversation

@blindzero

Copy link
Copy Markdown
Owner

Summary

An entitlement is identified by Kind + Id. Kind now belongs to the entitlement reference; a step-level Kind only defines a scope (what a prune may remove, what a resolver lists). Providers own their supported Kinds and reject everything else before changing anything. The design was folded into docs/extend/providers.md (section Entitlement providers), the step help and the context resolver docs.

Steps

  • IdLE.Step.EnsureEntitlement: unchanged (With.Entitlement.Kind, one entitlement per step).
  • IdLE.Step.PruneEntitlements / PruneEntitlementsEnsureKeep: With.Kind stays required as the prune scope. Keep[].Kind is optional and inherits With.Kind; a different Kind fails the step before anything is listed or changed. Previously such an entry was matched by Id only and EnsureKeep granted it with the foreign Kind.

Providers

  • AD supports Group only. Grant, Revoke and Resolve no longer treat every Kind as a group (an AdministrativeUnit entitlement Sales added the user to a group Sales). ListEntitlements accepts and validates Kind, so a prune with an unsupported Kind fails instead of silently removing nothing.
  • Entra ID supports Group and AdministrativeUnit. ListEntitlements throws for other Kinds (e.g. 'Groups') instead of returning nothing. The bulk methods validate all entries before changing any membership. Unreachable "default to Group" branches were removed.
  • Kinds compare case-insensitively; providers return the canonical casing. Mock still accepts any Kind.
  • ResolveEntitlement(Entitlement[, AuthSession]): the unused Kind parameter is removed.

Context resolvers

  • IdLE.Entitlement.List accepts an optional With.Kind. It is passed to ListEntitlements when the provider declares Kind, and the result is always filtered to it. Entra ID then skips Administrative Unit calls, so group-only workflows no longer need AdministrativeUnit.Read.All (the provider docs claimed this before, but it only held for steps).
  • With.Kind is validated by the workflow schema (non-empty string, only for IdLE.Entitlement.List).
  • A second resolver for the same capability, provider and auth session now fails. Previously it silently replaced the first result.

Examples / docs

  • Templates no longer repeat Keep[].Kind; the mock resolver example shows With.Kind.
  • providers.md, context-resolver.md, capabilities.md, AD / Entra ID / Mock provider references; step and cmdlet references regenerated.

Breaking changes

No compatibility layer, as for #324.

  • Prune Keep[].Kind different from With.Kind fails; use one prune step per Kind.
  • Provider ResolveEntitlement($Kind, $Entitlement, $AuthSession) becomes ResolveEntitlement($Entitlement, $AuthSession).
  • AD and Entra ID reject unsupported Kinds.
  • Duplicate resolvers (same capability, provider, auth session) fail planning.

Not included

Plan-time Kind validation (providers declaring their Kinds) is deferred to after v1.0; it can be added as an optional provider method without breaking this contract.

Testing

  • Regression tests: prune Keep entry with a different Kind (both steps, no changes made); AD rejects AdministrativeUnit instead of resolving a group; AD prune with an unsupported Kind fails without changes; Entra ID ListEntitlements with a misspelled Kind; Entra ID bulk methods with an unsupported Kind change nothing; duplicate resolvers.
  • New cases: Keep entries inherit With.Kind (including EnsureKeep grants); ResolveEntitlement receives only the entitlement; canonical Kind casing; resolver With.Kind with and without a provider Kind parameter; resolver Kind schema validation.
  • ./tools/Invoke-IdlePesterTests.ps1: 1092 passed, 0 failed.
  • ./tools/Invoke-IdleScriptAnalyzer.ps1: no findings.
  • ./tools/Test-DocsConsistency.ps1: PASS.

Closes #289

🤖 Generated with Claude Code

blindzero and others added 7 commits November 1, 2026 18:27
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eEntitlement (#289)

- AD supports Kind 'Group' only. Grant/Revoke/Resolve no longer resolve any
  Kind as a group, and ListEntitlements accepts and validates Kind.
- Entra ID supports 'Group' and 'AdministrativeUnit'. ListEntitlements throws
  for other Kinds instead of returning nothing; the bulk methods validate all
  entries before changing any membership; unreachable "default to Group"
  branches removed.
- Kind is returned in canonical casing.
- ResolveEntitlement(Entitlement[, AuthSession]) takes the Kind from the
  entitlement; the unused Kind parameter is removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PruneEntitlements and PruneEntitlementsEnsureKeep apply With.Kind to Keep
entries. An explicit Keep[].Kind must match With.Kind; a different Kind fails
the step before anything is listed or changed (it was matched by Id only and
granted with the foreign Kind by EnsureKeep). Step help and examples omit the
redundant Keep[].Kind.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… resolvers (#289)

- IdLE.Entitlement.List resolvers accept an optional With.Kind. It is passed
  to ListEntitlements when the provider declares Kind (Entra ID then skips
  Administrative Unit calls and their Graph permissions), and the result is
  always filtered to that Kind.
- A second resolver for the same capability, provider and auth session fails
  instead of silently replacing the first result.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…#289)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
)

- docs/extend/providers.md: entitlement provider contract (methods, supported
  Kinds per provider, ResolveEntitlement migration).
- Context resolver docs and capability reference: With.Kind for
  IdLE.Entitlement.List, one resolver per capability/provider/session.
- Provider references: supported Kinds; Entra ID resolver permissions note.
- Regenerated step and cmdlet references.
- Remove the design document.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Test-IdleWorkflow now rejects a resolver With.Kind that is not a non-empty
string or is used with a capability other than IdLE.Entitlement.List,
instead of failing only at planning (wrapped as a provider error) or being
ignored.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-01T18:03:03.659346Z 2b0c0a9 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@claude

claude Bot commented Nov 1, 2026

Copy link
Copy Markdown
Contributor

Verdict: PASS — no blocking issues; Kind validation, prune-scope inheritance and resolver dedup are consistent with AGENTS.md and the linked issue.

No CRITICAL, MAJOR or MINOR findings. Tests, docs, regenerated references and breaking-change notes are included in the PR.

@github-actions

github-actions Bot commented Nov 1, 2026

Copy link
Copy Markdown

Code Coverage Report

Overall Project 78.06% 🍏

There is no coverage information present for the Files changed

@blindzero
blindzero merged commit cc359e8 into main Nov 1, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Entitlements: Check and improve type logic

1 participant