Skip to content

Refactor eventing: unify WriteEvent/EventSink into one contract and remove ScriptBlock sinks #22

@blindzero

Description

@blindzero

Problem

Event emission currently has two paths (Context.WriteEvent and Context.EventSink) and some implementations accept ScriptBlock sinks that get invoked directly. This is both confusing (inconsistent behavior across pipeline/host) and a security risk (potential RCE if an untrusted sink is passed through).

Goal

Provide one supported engine eventing path with a clear, testable contract:

  • Engine calls Context.EventSink.WriteEvent($event) (or equivalent) only.
  • No direct invocation of ScriptBlocks by the engine.

Proposed design

  • Introduce a sink contract (PowerShell-friendly):
    • Context.EventSink MUST be an object that implements WriteEvent([object] $event) (or WriteEvent([IdleEvent]$event) if type exists).
    • Engine validates that EventSink is not a ScriptBlock and has a callable WriteEvent member.
  • Deprecate and later remove Context.WriteEvent.
    • During transition: map Context.WriteEvent -> adapter sink internally (opt-in / compatibility) OR keep for one release with warning.
  • Update Write-IdleEvent to use the sink contract only.

Acceptance criteria

  • Engine emits events consistently in the normal pipeline without host-specific hacks.
  • Engine does not accept or invoke ScriptBlocks as sinks.
  • IdLE.Step.EmitEvent (and demos) emit events using the unified sink path.
  • Pester tests cover:
    • event emission works with a sink object
    • ScriptBlock sink is rejected by default
    • legacy path behavior (if kept temporarily) is covered and emits a warning

Notes

This change is expected to be a breaking-change unless we provide a short-lived compatibility shim.

Metadata

Metadata

Assignees

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions