Skip to content

Step contract: typed With schema, provider handle and handler results (#324) - #348

Merged
blindzero merged 6 commits into
mainfrom
feature/324-step-contract
Nov 1, 2026
Merged

blindzero merged 6 commits into
mainfrom
feature/324-step-contract

Conversation

@blindzero

@blindzero blindzero commented Nov 1, 2026 •

Copy link
Copy Markdown
Owner

Closes #324

Summary

Moves the boilerplate every step handler repeated (With checks, provider lookup, auth session, result building)
into the engine and introduces a typed WithSchema. Handlers now contain only domain logic; DisableIdentity
shrinks from ~50 lines to 3. Contract, error codes and migration: docs/extend/steps.md.

Step metadata catalog

  • Provider = @{ DefaultAlias = '...'; AuthSessionNameFromAlias = $true } (optional) replaces per-step provider handling.
  • Typed WithSchema.Keys: Type (String, Int, Bool, Hashtable, Array, Any), Required, Default,
    AllowedValues, AllowEmpty, nested Keys / Items, AllowAdditionalKeys.
  • With is validated at plan time with path-aware errors (WithKeyMissing: ... With.Entitlement.Kind);
    defaults and the provider alias are written into the plan. No implicit type coercion.
  • Common keys Provider, AuthSessionName, AuthSessionOptions exist only for steps that declare Provider.

Step handler contract

  • Parameters: -With (required), -Provider (iff metadata declares a provider), -Context / -Step (optional).
  • -Provider is an IdLE.ProviderHandle: Invoke(Method, Args), HasMethod, HasParameter. It acquires the
    auth session once per attempt, inserts it where the method declares AuthSession and wires EventSink.
  • Result: $null or @{ Changed; Data; State }; the engine builds IdLE.StepResult. Failures are exceptions.

Error codes

LegacyWithSchema, InvalidWithSchema, WithKeyMissing, WithKeyUnknown, WithKeyTypeMismatch,
WithValueNotAllowed, LegacyStepHandler, InvalidStepHandlerSignature, InvalidStepHandlerResult,
ProviderNotSupplied, ProviderMethodNotImplemented.

Bugs fixed along the way

  • Context.AcquireAuthSession rejected the empty name, so steps without With.AuthSessionName failed against
    providers whose methods take AuthSession (e.g. AD).
  • Copy-IdleDataObject and template resolution unrolled single-element arrays and turned empty arrays into $null.
  • Examples used the never-supported @{ ValueFrom = '...' }; they now use templates.
  • Two step tests used non-existent step types.

Breaking changes

  • Catalogs with RequiredKeys/OptionalKeys fail with LegacyWithSchema; handlers without -With fail with LegacyStepHandler.
  • Wrongly typed With values now fail at plan time (e.g. numbers previously coerced to strings).
  • EmitEvent no longer accepts Provider / AuthSession* keys.
  • PruneEntitlements*: Skipped moved to Data.Skipped; EnsureAttributes: results under Data.Attributes.
  • Invoke-IdleProviderMethod removed and Test-IdleProviderMethodParameter no longer exported (replaced by the provider handle).

Follow-ups

Tests and checks

  • New tests/Core/StepContract.Tests.ps1 (schema matrix, catalog contract, handler signature/result, provider handle)
  • Step tests run handlers through the engine-like Invoke-IdleTestStepHandler
  • Pester: 1002 passed, 0 failed; PSScriptAnalyzer: no findings
  • docs/reference/steps* regenerated (With tables now come from the catalog schema)

🤖 Generated with Claude Code

blindzero and others added 4 commits November 1, 2026 12:53
Typed WithSchema, provider declaration in the catalog, provider handle,
handler result contract and error codes. Includes implementation notes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Catalog: Provider = @{ DefaultAlias; AuthSessionNameFromAlias } and a typed
  WithSchema (Type, Required, Default, AllowedValues, AllowEmpty, nested Keys/Items);
  RequiredKeys/OptionalKeys fail with LegacyWithSchema
- With is validated at plan time with path-aware errors; defaults and the
  provider alias are written into the plan; common keys (Provider,
  AuthSessionName, AuthSessionOptions) exist only for steps that declare Provider
- Handlers receive -With, -Provider (IdLE.ProviderHandle) and optionally
  -Context/-Step; pre-1.0 handlers fail with LegacyStepHandler
- Provider handle resolves the provider, acquires the auth session once per
  attempt, inserts it where the method declares it and wires EventSink
- Handlers return $null or @{ Changed; Data; State }; the engine builds
  IdLE.StepResult, failures are exceptions (InvalidStepHandlerResult otherwise)
- Invoke-IdleProviderMethod removed; Test-IdleProviderMethodParameter is private
- Fix: Context.AcquireAuthSession accepts an empty name (default session)
- Fix: Copy-IdleDataObject and template resolution kept single-element and
  empty arrays intact

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Catalogs of IdLE.Steps.Common, DirectorySync and Mailbox use Provider and
  typed WithSchema (defaults for EmitEvent Level, DirectorySync wait options,
  EnsureEntitlement State)
- Handlers contain only domain logic and return @{ Changed; Data; State }
- PruneEntitlements and PruneEntitlementsEnsureKeep share a private operation;
  Skipped moved to Data.Skipped, EnsureAttributes results to Data.Attributes
- MailboxGetInfo returns its mailbox under State
- Examples use templates instead of the unsupported ValueFrom syntax
- Step tests run handlers through the engine-like Invoke-IdleTestStepHandler

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

- steps.md: step metadata contract and step handler contract
- extensibility.md: adding steps and registering handlers
- Step reference generator reads With keys (type, required, default, notes)
  from the catalog schema instead of parsing handler source; references regenerated

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-01T11:58:09.825895Z baccb8d 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

Reviewed the core of the new step contract (New-IdleProviderHandle, New-IdleStepHandlerArguments, ConvertTo-IdleStepResult): no trust-boundary or correctness defects found, and the raw provider is not exposed to steps. This is a partial review: the diff is about 417 KB, and I could not run Pester, PSScriptAnalyzer or the CI status checks in this environment. Step handlers, catalogs, tests and docs were not reviewed line by line.

Findings: no CRITICAL, MAJOR or MINOR.

@github-actions

github-actions Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

Code Coverage Report

Overall Project 77.19% 🍏

There is no coverage information present for the Files changed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: baccb8dd90

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

steps.md now carries the full contract: schema rules, provider handle
members, result keys, an error code table and a migration section (as in
events.md). The separate design document is removed.

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

claude Bot commented Nov 1, 2026

Copy link
Copy Markdown
Contributor

Verdict: PASS

No CRITICAL findings in the parts I reviewed: the IdLE.ProviderHandle and the With schema validation. Auth is acquired through Context.AcquireAuthSession, the raw provider is not exposed to steps, and no secrets reach events.

Findings: none reported (no CRITICAL, MAJOR or MINOR).

Limits of this review: the diff is very large (85 files). I did not review the other changed files in depth: the step handlers, the schema converter, the metadata catalogs, the tests and the generated docs. I also could not run the Pester suite or PSScriptAnalyzer here, so test results are unverified.

…der handle (#324)

Test-IdleProviderMethodParameter detected 'authsession' case-insensitively, but the
insert position used a case-sensitive IndexOf, so the session was appended and bound
to the wrong parameter. Found by review.

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

claude Bot commented Nov 1, 2026

Copy link
Copy Markdown
Contributor

Verdict: PASS

The new step contract (typed WithSchema, IdLE.ProviderHandle, engine-built IdLE.StepResult) keeps to the architecture and security rules. Auth sessions go through Context.AcquireAuthSession and the raw provider is not exposed. Handler signatures and results are validated with actionable error codes. Per-attempt handles keep the auth session cache fresh across retries. Docs, generated references and tests are updated.

Findings: none (CRITICAL 0, MAJOR 0, MINOR 0).

Scope note: I read the core engine files in full (New-IdleProviderHandle, New-IdleStepHandlerArguments, ConvertTo-IdleStepResult, and the Invoke-IdlePlanObject call sites). I did not read every step handler, schema converter or test file. I did not run the Pester or ScriptAnalyzer suites.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Design: move step boilerplate into the engine and introduce typed With keys

1 participant