Skip to content

Refactor Steps to be strictly provider-agnostic (StepTypes -> Capabilities <- Providers) #98

@blindzero

Description

@blindzero

Summary

We want to strictly enforce the architectural rule:

Steps → StepTypes → RequiredCapabilities ← Providers

Steps must be fully provider-agnostic:

  • no product/provider-specific naming in step packs
  • no product-specific defaults inside steps (e.g., AuthSessionName)
  • steps only call provider contract methods via the provider abstraction (no direct cmdlets, no imports, no remote/network at step scope)

A repository review shows one primary violation of this strictness:

  • The TriggerDirectorySync step implementation is provider-agnostic in code, but the step pack and documentation are Entra Connect-specific:
    • Module name: IdLE.Steps.DirectorySync.EntraConnect
    • Help/defaults mention “Entra Connect”
    • Default AuthSessionName is EntraConnect

This issue refactors the DirectorySync step pack to be generic and updates all references accordingly.

Motivation / Rationale

  • Keep Steps reusable across providers that implement the same capability set.
  • Avoid baking provider/product identity into Step packs or defaults.
  • Ensure adding a second provider for the same StepType requires no changes to Steps (only provider implementation + capability declaration).
  • Make documentation consistent with the capability model.

Scope

In scope

  • Refactor the DirectorySync step pack and TriggerDirectorySync step to be strictly generic.
  • Update step registry auto-discovery to map StepType → handler for the new generic module.
  • Update docs/tests/examples that reference the old module name and Entra Connect wording.

Out of scope

  • Capability taxonomy redesign (already uses generic IdLE.DirectorySync.*).
  • Provider-side functionality changes (except renames required by the refactor).
  • Broader module packaging decisions (tracked separately).

Current findings (what violates strict generic Steps)

1) Provider-specific step pack naming

  • src/IdLE.Steps.DirectorySync.EntraConnect/* is provider/product-specific by name.

2) Provider-specific wording and defaults inside the step

Invoke-IdleStepTriggerDirectorySync:

  • Help/description mentions “Entra Connect directory sync cycle”.
  • Defaults include:
    • Name = 'Trigger Entra Connect sync'
    • AuthSessionName = 'EntraConnect'

3) Documentation inherits provider specificity

docs/reference/steps.md describes TriggerDirectorySync as “Triggers an Entra Connect directory sync cycle …”.

Target state (definition)

Step pack & step implementation

  • A generic step pack exists:
    • Module name: IdLE.Steps.DirectorySync
  • The step remains provider-agnostic and references only capabilities/contract methods:
    • StepType: IdLE.Step.TriggerDirectorySync
    • RequiredCapabilities: IdLE.DirectorySync.Trigger, IdLE.DirectorySync.Status
    • Provider contract methods (example):
      • StartSyncCycle(PolicyType, AuthSession)
      • GetSyncCycleState(AuthSession)
  • No provider-specific defaults:
    • Default AuthSessionName should be generic (e.g., DirectorySync) or omitted (null) so workflows/templates set it explicitly.
    • Default Name should be provider-neutral (e.g., “Trigger directory sync”).

Templates remain provider-specific (allowed)

  • Provider-specific workflows (e.g., Entra Connect) can live in templates and specify:
    • provider alias (e.g., DirectorySync)
    • auth session name/options (e.g., EntraConnect)
    • provider module to import
      This provider specificity must not leak into Step packs.

Acceptance criteria

Strict provider-agnostic steps

  • IdLE.Steps.DirectorySync contains Invoke-IdleStepTriggerDirectorySync (same StepType, generic wording).
  • No step code in any step pack:
    • imports product modules
    • calls product-specific cmdlets directly
    • requires RSAT/ADSync/Graph/etc.
    • performs network/remote operations directly
  • Any product/provider-specific behavior is confined to provider modules and templates.

Engine discovery / StepRegistry

  • Get-IdleStepRegistry auto-registers IdLE.Step.TriggerDirectorySync when IdLE.Steps.DirectorySync is loaded:
    • resolves handler via module-qualified invocation (same pattern as IdLE.Steps.Common).

Tests

  • Update existing Pester tests to import the new module name and pass.
  • Invoke-IdleStepTriggerDirectorySync.Tests.ps1 references IdLE.Steps.DirectorySync (not EntraConnect).
  • Tests remain fully mockable (no real systems required).

Documentation

  • docs/reference/steps.md updates TriggerDirectorySync description to provider-neutral wording.
  • Any references to IdLE.Steps.DirectorySync.EntraConnect are removed or replaced with:
    • generic steps pack name, and
    • provider-specific references only in template sections.

Compatibility

  • Provide a clear migration note in docs:
    • old module name → new module name
  • Decide on backward compatibility for module name:
    • preferred: breaking rename (pre-1.0), update all internal references/tests/docs accordingly.

Implementation tasks (agent-ready)

1) Create generic DirectorySync step pack

  • Create src/IdLE.Steps.DirectorySync/ as a new module:
    • IdLE.Steps.DirectorySync.psd1
    • IdLE.Steps.DirectorySync.psm1
    • Public/Invoke-IdleStepTriggerDirectorySync.ps1 (moved)
  • Remove or deprecate src/IdLE.Steps.DirectorySync.EntraConnect/:
    • preferred: remove after updating references (breaking but acceptable pre-1.0)

2) Refactor Invoke-IdleStepTriggerDirectorySync

  • Update help text to be provider-neutral:
    • replace “Entra Connect” with “directory sync”
  • Update default step object example/shape:
    • Name = 'Trigger directory sync'
    • AuthSessionName:
      • either omit by default, or use generic value (e.g., DirectorySync)
  • Ensure the step still uses only provider abstraction (Invoke-IdleProviderMethod) and does not add any external dependencies.

3) Update StepRegistry auto-registration

  • Update src/IdLE.Core/Private/Get-IdleStepRegistry.ps1:
    • Add built-in registration for IdLE.Step.TriggerDirectorySync using:
      • CommandName = 'Invoke-IdleStepTriggerDirectorySync'
      • ModuleName = 'IdLE.Steps.DirectorySync'

4) Update tests

  • Update tests/Invoke-IdleStepTriggerDirectorySync.Tests.ps1:
    • import and reference IdLE.Steps.DirectorySync
    • update any expectations that mention “Entra Connect”
  • Run full Pester suite; ensure green.

5) Update docs

  • Update docs/reference/steps.md section TriggerDirectorySync to provider-neutral text.
  • Add a short migration note (pre-1.0 breaking rename acceptable).

6) Update examples/templates (if referenced)

  • If any workflows/import instructions reference IdLE.Steps.DirectorySync.EntraConnect, update to IdLE.Steps.DirectorySync.
  • Keep Entra Connect specifics in templates (provider module + auth session naming).

Suggested labels

  • refactor
  • steps
  • documentation
  • testing
  • (optional) breaking change

Notes / Dependencies

  • This issue is compatible with the “non-blocking baseline NestedModules” policy; it does not require changing what IdLE loads by default.
  • If a separate issue introduces “packs”, IdLE.Steps.DirectorySync can be used by multiple providers (Entra Connect today, others later).

Metadata

Metadata

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions