Skip to content

[Task] Add Health Metadata, Tags, and Diagnostics #16

Description

@rian-be

Summary

Extend the structured plugin health model with explicit metadata for health classification, filtering, and diagnostics.

The goal is to allow plugins and the AuthKit host to attach meaningful tags and diagnostic information to PluginHealthResult without overloading the health status itself or introducing plugin fields into the core contract.

Goal

Provide structured and extensible metadata model that allows health results to be:

  • categorized,
  • filtered,
  • grouped,
  • and enriched with plugin diagnostic information.

The change must preserve the strongly typed semantics introduced by D1–D2 and remain additive and backward compatible.

Background

PluginHealthResult provides the core health state:

Healthy
Degraded
Unhealthy

However, health status alone does not provide enough information for filtering or categorizing health results.

For example, host may need to distinguish between:

Database
Cache
ExternalService
Security
Storage
Network

or filter health results according to operational categories such as:

critical
startup
readiness
liveness
dependency
external

Plugins may also need to expose additional diagnostic information without requiring changes to the core plugin contract.

D5–D6 introduce structured support for health tags and diagnostic metadata.

Scope

D5. Health Tags

Add explicit health tags that can be used to categorize and filter PluginHealthResult instances.

Tags represent stable classification metadata and must remain separate from:

  • Status,
  • Reason,
  • and arbitrary diagnostic Data.

The preferred contract shape is:

IReadOnlyCollection<string> Tags

Tags should support scenarios such as:

database
cache
external
critical
readiness
liveness
security

The exact property name and collection type must remain consistent with existing AuthKit.Plugins.Abstractions conventions.

D6. Structured Diagnostic Metadata

Define and validate the intended use of the Data property introduced by D1–D2.

Data must provide an extensibility point for plugin diagnostic information without redefining the strongly typed health contract.

Examples may include:

database_name
endpoint
queue_depth
connection_count
dependency_version
certificate_expiry

Diagnostic metadata must remain distinct from health classification and health status.

Proposed Contract

The health result model should support explicit tags and optional diagnostic data.

A preferred shape is:

public sealed record PluginHealthResult(
    PluginHealthStatus Status,
    string? Reason = null,
    IReadOnlyDictionary<string, object>? Data = null,
    IReadOnlyCollection<string>? Tags = null);

The exact parameter order may be adjusted to match the conventions of the existing abstraction API.

All public members must include complete XML documentation.

Requirements

Health Tags

Tags must represent classification metadata.
They must not redefine the meaning of the health result.

For example:

Status: Degraded
Tags:
    database
    critical

means that the health result is explicitly Degraded, while the tags provide additional classification.

The following must remain semantically distinct:

Status
Reason
Tags
Data

Tags must not be used as a replacement for PluginHealthStatus.

For example:

Tags = ["healthy"]

must not be treated as equivalent to:

Status = Healthy

Tag Filtering

The health model must allow the host to inspect and filter results using tags.
The core abstraction does not need to define a complete query or filtering API.

However, tags must be exposed through the contract in a form that allows host-side filtering without parsing:

Reason

or arbitrary:

Data

values.

For example:

Tag: readiness

must remain directly discoverable as structured metadata.

Tag Semantics

Tags should be:

  • stable,
  • machine readable,
  • suitable for filtering,
  • and independent from presentation text.

Tags should not contain user facing diagnostic messages.

For example:

"database"
"external"
"critical"

are appropriate tags.

Values such as:

"Database connection failed at 10:32"

are not appropriate tags and should instead be represented through Reason or Data.

The contract must not require fixed global registry of tags in this task.
Plugins may define their own tags where appropriate.

Diagnostic Data

Data represents plugin structured diagnostic metadata.

It may contain values such as:

endpoint
queue_depth
retry_count
connection_state
certificate_expiry

The core health contract must not require all plugins to use the same diagnostic keys.
However, diagnostic data must not silently redefine known health semantics.

For example:

Data["status"] = "healthy";

must not override:

Status = PluginHealthStatus.Unhealthy;

The strongly typed properties of PluginHealthResult always take precedence over conflicting values contained in Data.

Separation of Concerns

The health result contract should maintain the following model:

PluginHealthResult
│
├── Status
│   └── Strongly typed health state
│
├── Reason
│   └── Human-readable explanation
│
├── Tags
│   └── Classification and filtering metadata
│
└── Data
    └── Plugin-specific diagnostic metadata

These responsibilities must remain distinct.
The host must not infer one category from another.

For example:

Data["critical"] = true

must not automatically create:

Tags = ["critical"]

Similarly:

Tags = ["database"]

must not automatically imply particular Status.

Backward Compatibility

The change must be additive.

Existing plugins must not be required to immediately provide tags or diagnostic metadata.

A health result without tags must remain valid.
A health result without diagnostic data must remain valid.

For example:

new PluginHealthResult(
    PluginHealthStatus.Healthy)

must remain valid health result.

The introduction of tags must not change the meaning of existing Status, Reason, or Data values.
Existing plugins, including DevTokens, must continue to compile and load without modification.

Serialization

Tags and diagnostic data must be serializable through the host health infrastructure.

The serialized representation must preserve the distinction between:

  • Status,
  • Reason,
  • Tags,
  • and Data.

The host must not merge tags into arbitrary diagnostic data or flatten diagnostic data into tags.

The exact endpoint representation is defined by the host.

Non Goals

This task does not include:

  • health check execution changes,
  • CancellationToken behavior,
  • host side health aggregation,
  • health result caching,
  • latency or execution duration measurement,
  • scoped IServiceProvider execution,
  • a fixed global registry of allowed health tags,
  • or complete health filtering/query API.

Those concerns are handled by other Section D sub issues or remain host specific.

Validation

Contract

  • PluginHealthResult supports explicit health tags.
  • Tags are exposed through a strongly typed collection.
  • Tags remain distinct from Status.
  • Tags remain distinct from Reason.
  • Tags remain distinct from diagnostic Data.
  • Data remains available for plugin diagnostic metadata.
  • All new public members include complete XML documentation.

Tags

  • A health result can be created without tags.
  • A health result can contain one or more tags.
  • Tags can be inspected directly by the host.
  • Tags can be used for host-side filtering.
  • Tags do not redefine or override PluginHealthStatus.
  • Tags do not require parsing Reason or Data.

Diagnostic Data

  • A health result can be created without diagnostic data.
  • Diagnostic data preserves plugin values.
  • Diagnostic data does not override strongly typed health properties.
  • Conflicting values in Data do not change Status, Reason, or Tags.
  • Data remains distinct from health classification metadata.

Serialization

  • Status is preserved during serialization.
  • Reason is preserved during serialization when present.
  • Tags are preserved during serialization when present.
  • Diagnostic Data is preserved during serialization when present.
  • Tags and diagnostic data remain structurally distinct.

Compatibility

  • Existing plugins compile without modification.
  • Existing health results without tags remain valid.
  • Existing health results without diagnostic data remain valid.
  • DevTokens` continues to compile and load successfully.

Build and Tests

  • dotnet build completes successfully with zero warnings.
  • Relevant unit tests pass.
  • Serialization tests pass.
  • PluginContractValidator successfully validates the updated contract.
  • DevTokens` continues to load successfully.

Acceptance Criteria

  • PluginHealthResult supports explicit, structured health tags.
  • Tags are distinct from health status, reasons, and diagnostic data.
  • Tags can be inspected and filtered by the host.
  • Plugin diagnostic information can be exposed through Data.
  • Strongly typed health properties always take precedence over conflicting diagnostic metadata.
  • Tags and diagnostic data remain structurally distinct during serialization.
  • Existing plugins remain compatible without requiring immediate changes.
  • 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

Assignees

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