Goal
Provide a first-party step pack that can trigger an Entra ID Connect (ADSync) sync cycle on an on-premises server and optionally wait until the cycle is finished.
Constraints:
- This cannot be triggered “from Entra in the cloud”; it must run against the on-premises Entra Connect server.
Start-ADSyncSyncCycle typically requires an elevated/admin execution context.
- No interactive prompts (headless engine). Elevation and authentication are the host’s responsibility via AuthSessionBroker.
Scope
In scope
- New step pack (separate module):
IdLE.Steps.DirectorySync.EntraConnect
- New provider implementation module:
IdLE.Provider.DirectorySync.EntraConnect
- Provider contract (lightweight PowerShell object contract)
- Auth session contract for remote execution (Wrapper / Handle)
- Tests (unit + provider contract tests) and docs/examples
Out of scope
- Host-side implementation details for creating an elevated remote session (that belongs to the host).
- Running real ADSync in CI.
Design
1) Step Type and module
- Step.Type:
IdLE.Step.TriggerDirectorySync
- Step implementation function:
Invoke-IdleStepTriggerDirectorySync
- Module:
src/IdLE.Steps.DirectorySync.EntraConnect/
2) Step metadata (RequiredCapabilities)
Because #89 removes workflow RequiresCapabilities, the step pack must provide metadata for this step:
RequiredCapabilities = @('IdLE.DirectorySync.Trigger', 'IdLE.DirectorySync.Status')
Rationale:
- Keeping this static avoids conditional capability logic in the engine.
- Even when
With.Wait = $false, advertising IdLE.DirectorySync.Status is acceptable and keeps planning deterministic.
3) Step inputs (With.*)
With must be a hashtable and is validated by the step.
Required:
With.AuthSessionName (string)
- Routing key for the AuthSessionBroker (recommended default in examples:
EntraConnect).
With.PolicyType (string)
- Allowed:
Delta, Initial (case-insensitive).
Optional:
With.Provider (string) — provider alias in Context.Providers (default: DirectorySync).
With.Wait (bool) — default: $false.
With.TimeoutSeconds (int) — default: 600.
With.PollIntervalSeconds (int) — default: 10.
With.AuthSessionOptions (hashtable, data-only) — forwarded to broker (e.g., { Role = 'EntraConnectAdmin' }).
4) Provider contract
The step calls a provider instance via Context.Providers[<ProviderAlias>].
Provider must implement:
Notes:
- The contract is intentionally not tied to a specific cmdlet name (e.g.
Get-ADSyncScheduler). The EntraConnect provider may use Get-ADSyncScheduler or another reliable signal; the contract only cares about InProgress.
5) AuthSession contract (Wrapper / Handle)
The host’s AuthSessionBroker must return an AuthSession whose payload is a remote execution handle for the Entra Connect server.
Minimum expected shape (trusted runtime object; not part of workflow data):
The provider uses only this handle (via AuthSession) and does not create its own sessions.
6) Elevation requirement (explicit)
If the remote execution context is not privileged enough to call Start-ADSyncSyncCycle, the provider must fail deterministically:
- Throw an error that is actionable and clearly indicates:
- missing privileges / elevation
- that the host must provide an elevated session via AuthSessionBroker
No interactive escalation (no UAC prompts, no credential prompts).
7) Step behavior
- Validate inputs early.
- Acquire auth session via:
Context.AcquireAuthSession(With.AuthSessionName, With.AuthSessionOptions)
- Call provider
StartSyncCycle(With.PolicyType, AuthSession).
- Emit events (see below).
- If
With.Wait is $true:
- poll
GetSyncCycleState(AuthSession) until InProgress = $false or timeout
- on timeout: fail with a clear error (
TimeoutSeconds, last known state)
8) Events
Use the standard event sink:
DirectorySyncTriggered (after trigger call returns)
DirectorySyncWaiting (first poll)
DirectorySyncPoll (optional, only if not too chatty; include attempt + state)
DirectorySyncCompleted (when finished)
DirectorySyncFailed (on any failure)
Event Data must be data-only and must not include secrets.
Implementation tasks
Step pack: IdLE.Steps.DirectorySync.EntraConnect
Provider: IdLE.Provider.DirectorySync.EntraConnect
Tests
-
Unit tests for the step:
- validates required keys
- triggers without wait
- triggers and waits (poll loop) until complete
- timeout path
- provider missing method surfaces actionable error
-
Provider contract tests:
GetCapabilities() returns the required capability ids
StartSyncCycle and GetSyncCycleState accept AuthSession parameter and behave with a mocked remote handle
No live ADSync / no real remoting in default CI.
Docs / examples
-
Add a minimal example workflow step using IdLE.Step.TriggerDirectorySync.
-
Example should demonstrate:
AuthSessionName = 'EntraConnect'
AuthSessionOptions = @{ Role = 'EntraConnectAdmin' } (if needed)
PolicyType = 'Delta'
Wait = $true (optional)
-
Update relevant docs pages if provider/step contracts are introduced or changed.
-
Regenerate step reference if new step is added.
Acceptance criteria
Definition of Done
Dependencies / References
Goal
Provide a first-party step pack that can trigger an Entra ID Connect (ADSync) sync cycle on an on-premises server and optionally wait until the cycle is finished.
Constraints:
Start-ADSyncSyncCycletypically requires an elevated/admin execution context.Scope
In scope
IdLE.Steps.DirectorySync.EntraConnectIdLE.Provider.DirectorySync.EntraConnectOut of scope
Design
1) Step Type and module
IdLE.Step.TriggerDirectorySyncInvoke-IdleStepTriggerDirectorySyncsrc/IdLE.Steps.DirectorySync.EntraConnect/2) Step metadata (RequiredCapabilities)
Because #89 removes workflow
RequiresCapabilities, the step pack must provide metadata for this step:RequiredCapabilities = @('IdLE.DirectorySync.Trigger', 'IdLE.DirectorySync.Status')Rationale:
With.Wait = $false, advertisingIdLE.DirectorySync.Statusis acceptable and keeps planning deterministic.3) Step inputs (With.*)
Withmust be a hashtable and is validated by the step.Required:
With.AuthSessionName(string)EntraConnect).With.PolicyType(string)Delta,Initial(case-insensitive).Optional:
With.Provider(string) — provider alias inContext.Providers(default:DirectorySync).With.Wait(bool) — default:$false.With.TimeoutSeconds(int) — default:600.With.PollIntervalSeconds(int) — default:10.With.AuthSessionOptions(hashtable, data-only) — forwarded to broker (e.g.,{ Role = 'EntraConnectAdmin' }).4) Provider contract
The step calls a provider instance via
Context.Providers[<ProviderAlias>].Provider must implement:
StartSyncCycle(PolicyType, AuthSession)Started(bool)Message(string, optional)GetSyncCycleState(AuthSession)InProgress(bool)State(string; e.g.,Idle,InProgress,Unknown)Details(hashtable or null; optional)Notes:
Get-ADSyncScheduler). The EntraConnect provider may useGet-ADSyncScheduleror another reliable signal; the contract only cares aboutInProgress.5) AuthSession contract (Wrapper / Handle)
The host’s AuthSessionBroker must return an AuthSession whose payload is a remote execution handle for the Entra Connect server.
Minimum expected shape (trusted runtime object; not part of workflow data):
Method:
InvokeCommand(CommandName, Parameters)CommandNameis a string.Parametersis a hashtable (data-only).Method:
Dispose()(optional but recommended)The provider uses only this handle (via
AuthSession) and does not create its own sessions.6) Elevation requirement (explicit)
If the remote execution context is not privileged enough to call
Start-ADSyncSyncCycle, the provider must fail deterministically:No interactive escalation (no UAC prompts, no credential prompts).
7) Step behavior
Context.AcquireAuthSession(With.AuthSessionName, With.AuthSessionOptions)StartSyncCycle(With.PolicyType, AuthSession).With.Waitis$true:GetSyncCycleState(AuthSession)untilInProgress = $falseor timeoutTimeoutSeconds, last known state)8) Events
Use the standard event sink:
DirectorySyncTriggered(after trigger call returns)DirectorySyncWaiting(first poll)DirectorySyncPoll(optional, only if not too chatty; include attempt + state)DirectorySyncCompleted(when finished)DirectorySyncFailed(on any failure)Event
Datamust be data-only and must not include secrets.Implementation tasks
Step pack:
IdLE.Steps.DirectorySync.EntraConnectInvoke-IdleStepTriggerDirectorySync.Invoke-IdleProviderMethod) or reuse a shared helper if already available to the new module.Get-IdleStepMetadataCatalog(per Step types should declare their own required capabilities (metadata-driven validation) #89 design).Provider:
IdLE.Provider.DirectorySync.EntraConnectImplement
GetCapabilities()returning:IdLE.DirectorySync.TriggerIdLE.DirectorySync.StatusImplement provider methods using the AuthSession remote execution handle:
Start-ADSyncSyncCycle -PolicyType <Delta|Initial>InProgressvia a reliable signal (implementation detail).Tests
Unit tests for the step:
Provider contract tests:
GetCapabilities()returns the required capability idsStartSyncCycleandGetSyncCycleStateacceptAuthSessionparameter and behave with a mocked remote handleNo live ADSync / no real remoting in default CI.
Docs / examples
Add a minimal example workflow step using
IdLE.Step.TriggerDirectorySync.Example should demonstrate:
AuthSessionName = 'EntraConnect'AuthSessionOptions = @{ Role = 'EntraConnectAdmin' }(if needed)PolicyType = 'Delta'Wait = $true(optional)Update relevant docs pages if provider/step contracts are introduced or changed.
Regenerate step reference if new step is added.
Acceptance criteria
IdLE.StepResultwith deterministic status.Context.AcquireAuthSession.Definition of Done
./tools/Invoke-IdlePesterTests.ps1)./tools/Invoke-IdleScriptAnalyzer.ps1)./tools/Generate-IdleStepReference.ps1)Dependencies / References
RequiresCapabilitieskeys.Context.AcquireAuthSession(Name, Options).