Skip to content

[Task] Extend the Plugin Health Check Contract #15

Description

@rian-be

Summary

Extend the AuthKit plugin health check contract to support asynchronous execution, multiple structured health results, and cancellation.

The goal is to allow plugins to report the health of multiple internal components or dependencies through the structured health model introduced in D1–D2 while ensuring that health checks can be cancelled safely by the host.

Goal

Provide first class plugin health check API that allows plugin to:

  • perform asynchronous health checks,
  • return multiple PluginHealthResult instances,
  • report the health of independent dependencies or capabilities,
  • and respect host provided cancellation.

The change must remain additive and preserve compatibility with existing IAuthKitPlugin implementations.

Background

A plugin may depend on multiple independent components, such as:

Database
Cache
External API
Message Queue
Key Store

A single health result is often insufficient to describe the health of all plugin dependencies.

For example:

Database -> Healthy
Cache -> Healthy
External API -> Degraded
Key Store -> Unhealthy

The plugin health contract should therefore support multiple structured health results.
Health checks may also involve asynchronous I/O and must support cancellation so that the host can stop long running or no longer relevant health operations.

Scope

D3. Multiple Health Results

Extend the plugin health contract so that health check can return multiple PluginHealthResult instances.

The contract should allow plugin to report the health of independent dependencies, capabilities, or internal components without forcing all diagnostic information into a single result.

The preferred result shape is:

IReadOnlyList<PluginHealthResult>

Each result must remain independently meaningful.

D4. Cancellation Support

The asynchronous health check contract must accept CancellationToken.

The preferred method shape is:

Task<IReadOnlyList<PluginHealthResult>> CheckHealthAsync(
    IServiceProvider serviceProvider,
    CancellationToken cancellationToken = default);

The exact return type and signature must remain consistent with existing AuthKit.Plugins.Abstractions conventions.

Proposed Contract

The structured health API introduced by this task should follow this shape:

Task<IReadOnlyList<PluginHealthResult>> CheckHealthAsync(
    IServiceProvider serviceProvider,
    CancellationToken cancellationToken = default);

The method allows plugin to perform health checks and return one or more structured results.

For example:

public async Task<IReadOnlyList<PluginHealthResult>> CheckHealthAsync(
    IServiceProvider serviceProvider,
    CancellationToken cancellationToken = default)
{
    return new[]
    {
        new PluginHealthResult(
            PluginHealthStatus.Healthy,
            "Database connection is available."),

        new PluginHealthResult(
            PluginHealthStatus.Degraded,
            "External service is responding slowly.")
    };
}

The exact implementation is plugin specific.

Requirements

Multiple Results

A health check may return one or more PluginHealthResult instances.
Each result should represent meaningful health observation.

Examples include:

Database
Cache
External API
Message Queue
Certificate Store

Plugins must not be required to expose every internal detail as separate health result.
A plugin may return single result when single overall health observation is sufficient.

The contract must therefore support both:

One result

and:

Multiple results

without requiring separate API.

Result Semantics

Each returned PluginHealthResult must preserve the semantics defined in D1–D2.

In particular:

Healthy
Degraded
Unhealthy

must remain distinguishable after being returned through the health check contract.
The contract must not collapse multiple results into a boolean value.

For example:

Healthy + Degraded

must not automatically become:

true

without explicit host aggregation rules.
Aggregation behavior is handled separately by the host in later Section D tasks.

Asynchronous Execution

The health check API must support asynchronous operations.

Plugins must be able to perform operations such as:

  • database connectivity checks,
  • network requests,
  • cache availability checks,
  • certificate validation,
  • external dependency checks,

without requiring synchronous blocking APIs.
Health checks should use asynchronous APIs where available.

Cancellation

The health check contract must accept CancellationToken.

The host may cancel health check when:

  • the health request is aborted,
  • a timeout expires,
  • the host is shutting down,
  • or the health operation is otherwise no longer required.

Plugins performing cancellable asynchronous operations must propagate and respect the supplied CancellationToken.

The contract must not silently ignore cancellation by design.

Where an underlying operation supports cancellation, the supplied token should be passed through.

For example:

await dependency.CheckAsync(cancellationToken);

rather than:

await dependency.CheckAsync(CancellationToken.None);

Cancellation Behavior

If cancellation occurs, the health check must not silently report a fabricated:

Healthy

or:

Unhealthy

result solely because execution was cancelled.

Cancellation must remain distinguishable from completed health result.
The host is responsible for defining how cancellation is represented at the endpoint or aggregation level.
This task only requires the plugin contract to support cancellation correctly.

Backward Compatibility

The change must be additive.
Existing plugins must not be forced to immediately implement the new structured health check method.

If an existing health check API is present on IAuthKitPlugin, this task must not replace its signature in breaking manner.

For example, replacing:

bool CheckHealth()

or:

Task<bool> CheckHealthAsync(...)

directly with:

Task<IReadOnlyList<PluginHealthResult>> CheckHealthAsync(...)

is considered breaking change.

The structured health API must therefore be introduced through compatibility preserving mechanism, such as:

  • a new method,
  • a default interface implementation,
  • or an explicitly defined adapter or migration path.

The chosen approach must ensure that existing IAuthKitPlugin implementations, including DevTokens, continue to compile and load without modification.

Default Behavior

The default behavior for plugins that do not provide custom structured health checks must be explicitly defined.

A plugin must not become implicitly unhealthy merely because it does not yet implement the extended health contract.

If default interface implementation is used, the default result should represent clearly defined compatibility state.

For example:

Healthy

with optional diagnostic information indicating that no custom health check is implemented.

The exact default representation must remain consistent across plugins and hosts.

Non Goals

This task does not include:

  • host side health aggregation,
  • health result caching,
  • health tags,
  • latency measurement,
  • /health endpoint design,
  • scoped IServiceProvider management,
  • or OpenAPI exposure.

Those concerns are handled by other Section D sub issues.

Validation

Contract

  • The plugin health contract supports asynchronous execution.
  • The structured health contract supports returning multiple PluginHealthResult instances.
  • The health check API accepts CancellationToken.
  • The API supports both single result and multi result health checks.
  • All new public members include complete XML documentation.

Multiple Results

  • A plugin can return single PluginHealthResult.
  • A plugin can return multiple PluginHealthResult instances.
  • Healthy, Degraded, and Unhealthy results remain distinguishable.
  • Multiple results are not implicitly collapsed into boolean value.
  • Each result preserves its Status, Reason, and diagnostic Data.

Cancellation

  • A plugin receives the CancellationToken provided by the host.
  • Cancellable asynchronous operations can receive the supplied token.
  • Cancellation is not silently converted into a fabricated health result.
  • A cancelled health operation remains distinguishable from a completed health check.

Compatibility

  • Existing IAuthKitPlugin implementations continue to compile without modification.
  • Existing health APIs are not replaced through breaking signature change.
  • Plugins that do not implement custom structured health checks have explicitly defined default behavior.
  • DevTokens continues to compile and load successfully.

Build and Tests

  • dotnet build completes successfully with zero warnings.
  • Relevant unit tests pass.
  • Integration tests covering health contract execution pass.
  • PluginContractValidator successfully validates the updated contract.
  • DevTokens continues to load successfully.

Acceptance Criteria

  • Plugins can expose structured health information asynchronously.
  • A health check can return one or more PluginHealthResult instances.
  • Each health result remains independently meaningful.
  • Health checks accept and support CancellationToken.
  • Cancellation is not silently converted into successful or failed health result.
  • Existing plugin implementations remain compatible without immediate source changes.
  • The default behavior for plugins without custom structured health checks is explicitly defined.
  • No existing health method signature is replaced in breaking manner.
  • PluginContractValidator passes.
  • DevTokens continues to compile and load successfully.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

P0Contract foundationadditiveAdditive, non-breaking changearea/health-checksPlugin health check contract/infra (Section D)contractChanges the plugin contractsub-taskChild task of an epic

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions