Problem Statement
IdLE is approaching v1.0.0. Consumers need a clear, reliable baseline for what is supported and what may change. Today, the repo contains a mix of documented and undocumented behavior and multiple modules, which creates risks for:
- accidental public API drift
- consumers depending on internal behavior
- expanded attack / leak surface through unintended exports
- unclear compatibility guarantees for workflows, steps, and providers
This issue must define the minimal supported surface and stable contracts for v1.0.0 and enforce them.
Proposed Solution
A) Supported surface (minimal) + enforcement
Definition (locked): Supported = exported + documented + stability-tested.
Source of truth (locked): Supported cmdlet surface = src/IdLE/IdLE.psd1 FunctionsToExport.
Supported cmdlets (v1.0 baseline):
Test-IdleWorkflow
New-IdleLifecycleRequest
New-IdlePlan
Invoke-IdlePlan
Export-IdlePlan
New-IdleAuthSessionBroker
Enforcement:
- Pester stability test imports
IdLE and asserts exported commands are exactly the allowlist above (no extras).
Reducing the “unsupported internal import gap” (defense-in-depth)
PowerShell cannot fully prevent users from importing internal nested modules by path.
Therefore, v1.0 uses defense-in-depth:
- Policy (primary control):
- Only IdLE meta-module exports are supported.
- Export minimization:
- Internal modules export only what is required for internal composition.
- Discourage direct import (recommended):
- Internal modules emit a warning on import:
Write-Warning "This module is internal/unsupported. Import 'IdLE' instead."
- Optional bypass:
IDLE_ALLOW_INTERNAL_IMPORT=1
- Security boundary:
- Output-boundary redaction rules must hold regardless of import path.
B) What counts as a “contract” for v1.0 (baseline)
Command contracts (supported cmdlets):
- Command name
- Parameter sets + parameter names
- Observable semantics (mandatory/optional/default behavior)
- Output type identity at a coarse level (e.g., PSTypeName / category), but not full internal property sets.
Data contracts (public artifacts):
- Workflow authoring contract (PSD1 structure + validation rules)
- Lifecycle request contract (host-facing)
- Plan export JSON contract (schema + semantics)
Explicit non-contracts:
- exact error message strings
- undocumented internal object properties
- internal module cmdlets
C) Canonical formats (locked)
- Workflow authoring format: PSD1 workflow definitions (validated by
Test-IdleWorkflow).
- Plan interchange format: JSON from
Export-IdlePlan.
Non-goal (v1.0):
- JSON as a workflow authoring format.
D) Validation strictness and null/empty semantics (locked)
- Unknown keys in workflow definitions: FAIL (strict authoring contract).
- Required contract fields (e.g., step
Name, step Type, request LifecycleEvent): FAIL if null/empty.
With payload values:
- allow
$null and empty strings as explicit values (supports “clear attribute” scenarios)
- required keys must exist, but values may be null/empty unless a step contract forbids it.
Step contracts must document required keys and per-key null/empty allowance.
E) Capability IDs baseline (v1.0) + rename before 1.0
Freeze all existing capability IDs as the v1.0 baseline, with one approved rename:
- Old (deprecated):
IdLE.Mailbox.Read
- New:
IdLE.Mailbox.Info.Read
Meaning:
- “Read mailbox metadata/configuration required by IdLE steps”
- “Does not read mailbox contents”
Migration policy (pre-1.0):
- Implement new capability ID.
- Treat
IdLE.Mailbox.Read as deprecated alias:
- if encountered, map to the new capability and emit a
DEPRECATED: warning during planning.
- Update step metadata and provider advertisements to use the new ID.
Known occurrences that must be updated:
src/IdLE.Provider.ExchangeOnline/Public/New-IdleExchangeOnlineProvider.ps1:153 — 'IdLE.Mailbox.Read'
src/IdLE.Steps.Mailbox/Public/Get-IdleStepMetadataCatalog.ps1:22 — # Returns: @('IdLE.Mailbox.Read')
src/IdLE.Steps.Mailbox/Public/Get-IdleStepMetadataCatalog.ps1:31 — RequiredCapabilities = @('IdLE.Mailbox.Read')
src/IdLE.Steps.Mailbox/Public/Get-IdleStepMetadataCatalog.ps1:36 — RequiredCapabilities = @('IdLE.Mailbox.Read', 'IdLE.Mailbox.Type.Ensure')
src/IdLE.Steps.Mailbox/Public/Get-IdleStepMetadataCatalog.ps1:41 — RequiredCapabilities = @('IdLE.Mailbox.Read', 'IdLE.Mailbox.OutOfOffice.Ensure')
tests/Providers/ExchangeOnlineProvider.Tests.ps1:175 — $caps | Should -Contain 'IdLE.Mailbox.Read'
v1.0 capability baseline list:
IdLE.DirectorySync.Status
IdLE.DirectorySync.Trigger
IdLE.Entitlement.Grant
IdLE.Entitlement.List
IdLE.Entitlement.Revoke
IdLE.Identity.Attribute.Ensure
IdLE.Identity.Create
IdLE.Identity.Delete
IdLE.Identity.Disable
IdLE.Identity.Enable
IdLE.Identity.Move
IdLE.Mailbox.OutOfOffice.Ensure
IdLE.Mailbox.Type.Ensure
IdLE.Mailbox.Info.Read (renamed from IdLE.Mailbox.Read)
F) Step capability ownership (already implemented; verified)
Step packs own required capabilities via step metadata catalogs; Core enforces this during planning.
Workflows do not declare capabilities themselves.
G) Deprecation mechanism (locked)
- Deprecated supported cmdlet/parameter MUST emit a
Write-Warning on use:
- prefix:
DEPRECATED:
- include: version deprecated in + planned removal major
- include: replacement/migration hint
Enforcement:
- Pester tests assert the warning exists.
H) Acceptance Criteria
- Supported surface policy is documented and enforced by stability tests.
- Workflow/request/plan contracts are documented (schema + semantics), with strict unknown-key behavior.
- Capability ID baseline is documented; renames use explicit deprecation + mapping.
IdLE.Mailbox.Info.Read is implemented; old ID is deprecated with warning + mapping until v1.0 ships.
- Baseline step contracts are documented and appear in the step catalog (no “Unknown” for baseline steps).
- Pester + PSScriptAnalyzer green; docs updated.
Impact
- Docs: new/updated documentation for supported surface, contracts, compatibility, deprecation.
- Tests: stability/snapshot tests for exports; contract invariants; deprecation tests.
- Compatibility: mostly additive; capability rename is pre-1.0 and mitigated via alias mapping + warnings.
Additional Context
- This issue is “policy + enforcement” for v1.0. It should avoid bundling unrelated refactors.
- Branch naming:
issues/16-<sanitized-title>
- Commits should be scoped: docs, tests, rename/migration, and catalog alignment separately.
Problem Statement
IdLE is approaching v1.0.0. Consumers need a clear, reliable baseline for what is supported and what may change. Today, the repo contains a mix of documented and undocumented behavior and multiple modules, which creates risks for:
This issue must define the minimal supported surface and stable contracts for v1.0.0 and enforce them.
Proposed Solution
A) Supported surface (minimal) + enforcement
Definition (locked): Supported = exported + documented + stability-tested.
Source of truth (locked): Supported cmdlet surface =
src/IdLE/IdLE.psd1FunctionsToExport.Supported cmdlets (v1.0 baseline):
Test-IdleWorkflowNew-IdleLifecycleRequestNew-IdlePlanInvoke-IdlePlanExport-IdlePlanNew-IdleAuthSessionBrokerEnforcement:
IdLEand asserts exported commands are exactly the allowlist above (no extras).Reducing the “unsupported internal import gap” (defense-in-depth)
PowerShell cannot fully prevent users from importing internal nested modules by path.
Therefore, v1.0 uses defense-in-depth:
Write-Warning "This module is internal/unsupported. Import 'IdLE' instead."IDLE_ALLOW_INTERNAL_IMPORT=1B) What counts as a “contract” for v1.0 (baseline)
Command contracts (supported cmdlets):
Data contracts (public artifacts):
Explicit non-contracts:
C) Canonical formats (locked)
Test-IdleWorkflow).Export-IdlePlan.Non-goal (v1.0):
D) Validation strictness and null/empty semantics (locked)
Name, stepType, requestLifecycleEvent): FAIL if null/empty.Withpayload values:$nulland empty strings as explicit values (supports “clear attribute” scenarios)Step contracts must document required keys and per-key null/empty allowance.
E) Capability IDs baseline (v1.0) + rename before 1.0
Freeze all existing capability IDs as the v1.0 baseline, with one approved rename:
IdLE.Mailbox.ReadIdLE.Mailbox.Info.ReadMeaning:
Migration policy (pre-1.0):
IdLE.Mailbox.Readas deprecated alias:DEPRECATED:warning during planning.Known occurrences that must be updated:
src/IdLE.Provider.ExchangeOnline/Public/New-IdleExchangeOnlineProvider.ps1:153—'IdLE.Mailbox.Read'src/IdLE.Steps.Mailbox/Public/Get-IdleStepMetadataCatalog.ps1:22—# Returns: @('IdLE.Mailbox.Read')src/IdLE.Steps.Mailbox/Public/Get-IdleStepMetadataCatalog.ps1:31—RequiredCapabilities = @('IdLE.Mailbox.Read')src/IdLE.Steps.Mailbox/Public/Get-IdleStepMetadataCatalog.ps1:36—RequiredCapabilities = @('IdLE.Mailbox.Read', 'IdLE.Mailbox.Type.Ensure')src/IdLE.Steps.Mailbox/Public/Get-IdleStepMetadataCatalog.ps1:41—RequiredCapabilities = @('IdLE.Mailbox.Read', 'IdLE.Mailbox.OutOfOffice.Ensure')tests/Providers/ExchangeOnlineProvider.Tests.ps1:175—$caps | Should -Contain 'IdLE.Mailbox.Read'v1.0 capability baseline list:
IdLE.DirectorySync.StatusIdLE.DirectorySync.TriggerIdLE.Entitlement.GrantIdLE.Entitlement.ListIdLE.Entitlement.RevokeIdLE.Identity.Attribute.EnsureIdLE.Identity.CreateIdLE.Identity.DeleteIdLE.Identity.DisableIdLE.Identity.EnableIdLE.Identity.MoveIdLE.Mailbox.OutOfOffice.EnsureIdLE.Mailbox.Type.EnsureIdLE.Mailbox.Info.Read(renamed fromIdLE.Mailbox.Read)F) Step capability ownership (already implemented; verified)
Step packs own required capabilities via step metadata catalogs; Core enforces this during planning.
Workflows do not declare capabilities themselves.
G) Deprecation mechanism (locked)
Write-Warningon use:DEPRECATED:Enforcement:
H) Acceptance Criteria
IdLE.Mailbox.Info.Readis implemented; old ID is deprecated with warning + mapping until v1.0 ships.Impact
Additional Context
issues/16-<sanitized-title>