You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add structured plugin documentation as declarative metadata, and keep XML doc extraction strictly as build/tooling separate from the runtime plugin contract.
H5 introduces PluginDocumentation, plain, JSON serializable metadata DTO plugin owns as static data (host/catalog reads it, no runtime generation). H6 is reframed as generate/populate step: an extractor tool (outside AuthKit.Plugins.Abstractions) reads the compiled plugin's C# XML doc and fills PluginDocumentation, which the catalog serializes to JSON for catalog/docs/UI. H6 is not part of the runtime contract.
Goal
Give every plugin single, serializable documentation shape the host and catalog can render without parsing prose READMEs, while keeping IAuthKitPlugin lean documentation is metadata plugin possesses, not runtime behavior it performs.
Problem
Plugin documentation lives only in prose the host/catalog cannot render it.
XML doc describes code: namespace, type, method, property, parameter, exception, returns. Product documentation such as Overview, Setup, Configuration, Endpoints, Health, Security is different model. Mapping between them is not obvious and must not be guessed.
GetDocumentation() as an executed method blurs two things: static plugin metadata vs runtime behavior. If the documentation is static, the API should read metadata, not generate a document.
Status architecture decision
Two candidate models were considered:
XML comments -> XML documentation -> extraction -> PluginDocumentation -> IAuthKitPlugin.Documentation (runtime)
Decision: documentation is static metadata you read, not behavior you execute. It is exposed as an accessor like property PluginDocumentation Documentation { get; } — never method that generates anything. H6 is tooling the runtime contract exposes only the shape plus its default. Nothing in the DTO or the property performs generation.
The binding condition:Documentation belongs on IAuthKitPluginonly if the host consumes it as runtime metadata a Plugin Catalog, Admin UI, or runtime discovery consuming /plugins/{id} -> JSON. If documentation is consumed only to generate a website, H5 does not exist in the runtime contract at all: the marker-driven H6 extractor alone is sufficient, producing static JSON/Markdown for the docs site.
flowchart LR
A["Plugin Assembly"] --> M["PluginManifest (what the plugin is)"]
A --> D["Documentation source<br/>XML-doc + markers"]
M --> C["Plugin Catalog"]
D --> E["H6 Extractor"]
E --> P["PluginDocumentation"]
P --> C
C --> J["JSON"]
C --> U["UI"]
C --> S["Docs"]
Loading
Clean boundaries:
manifest = what the plugin is and what it needs,
documentation = how the plugin works / how to use it,
runtime contract = what the host can do with the plugin,
extractor = tooling,
catalog = presentation/read.
Scope
ID
Element
Shape
Boundary
H5
PluginDocumentation
declarative, JSON-serializable metadata DTO + accessor property on IAuthKitPlugin
part of AuthKit.Plugins.Abstractions (shape only) only if runtime catalog/admin consumes it
H6
XML doc extraction
build/tooling generator that populates PluginDocumentation
outside the runtime plugin contract
Proposed Contract (H5)
publicsealedrecordPluginDocumentation{publicIReadOnlyCollection<PluginDocumentationSection>Sections{get;init;}=[];publicIReadOnlyDictionary<string,string>Parameters{get;init;}=newDictionary<string,string>();}publicinterfaceIAuthKitPlugin{// accessor like metadata never generates anything at runtimePluginDocumentationDocumentation=>new();}
Documentation is property, not method, so the semantics are unambiguous: Documentation is metadata; an operation would be GetDocumentation(). If GetDocumentation() is kept for API reasons, the ADR must state it is accessor like and performs no generation the property form is preferred.
Default new() keeps every existing plugin compatible and valid.
Parameters (MVP) is descriptive only: name -> short description of what the configuration entry means, never an actual value. If the catalog later needs structured rendering (Name, Description, Type, Required, Default), the model becomes PluginDocumentationParameter(Name, Description) as an IReadOnlyCollection only when real requirement demands it no abstraction now.
XML doc -> Sections (H6) explicit, marker-driven mapping
XML doc describes code (types, members, parameters) product sections such as Setup, Security, Configuration are different model. The extractor MUST NOT infer sections from class names, member lists, or parameter names.
Rules:
The marker is [PluginDocumentationSection("...")] distinct from the PluginDocumentation DTO, so there is no name collision:
Marker is opt-in. Only elements explicitly marked are extracted:
marked element + missing/hollow XML documentation -> build warning (author declared the element for docs but provided none),
XML documentation present but no marker → ignored (normal internal code /// <summary>Internal helper…</summary> must never enter plugin docs).
Each marked element's XML doc (<summary>, <remarks>, member docs) feeds the named PluginDocumentationSection(Section, Content).
An alternative explicit XML doc convention is acceptable provided it is deterministic and documented once. No name -> Overview, no param -> Configuration inference.
Decisions
H6 is tool, not the contract. The extractor lives in the repository's tools/build layer, never in AuthKit.Plugins.Abstractions.
PluginDocumentation is documentation DTO, not platform API: it holds plain records, strings, collections, and round trips to JSON with no runtime logic.
Documentation stays on IAuthKitPlugin only for runtime consumption (catalog/admin//plugins/{id}). Pure static site generation needs no runtime API alone suffices.
Boundary: Section H remains Observability, DX and tests. Documentation is metadata DTO plus generator IAuthKitPlugin is not home for every platform feature.
Validation
PluginDocumentation serializes to and from JSON without loss.
Default (new()) is empty but valid; existing plugins compile unchanged.
Documentation is a property (or documented accessor like method) that never generates at runtime.
Parameters contains descriptions only no runtime configuration values leak in.
Extractor (H6) produces PluginDocumentation from explicitly marked XML doc unmarked code is ignored.
Marked element with no XML documentation -> build warning.
No section is inferred from class/member/parameter naming.
Catalog renders plugin documentation from the serialized object without parsing README.
Acceptance Criteria
Plugins possess structured, serializable documentation metadata through the contract shape (and only if runtime consumer exists otherwise H6 tooling alone).
XML doc extraction is provided as tooling that populates that shape, outside the runtime contract.
Section mapping is deterministic, marker driven, and opt-in.
Existing plugins are unaffected (new() default) DevTokens/DevTools compile and load.
Non Goals
No runtime documentation generation by the plugin Documentation is metadata access only.
No documentation rendering engine in the contract (host concern).
No heuristic/magical XML doc -> section mapping.
No warnings for well documented but unmarked code the marker is opt-in.
No configuration values inside PluginDocumentation (descriptive Parameters only).
No .Parameters abstraction beyond the MVP dictionary until real catalog requirement appears.
No XML doc extractor inside AuthKit.Plugins.Abstractions tooling only.
No expansion of Section H beyond observability/DX/tests docs remain metadata DTO + generator
Summary
Add structured plugin documentation as declarative metadata, and keep XML doc extraction strictly as build/tooling separate from the runtime plugin contract.
H5 introduces
PluginDocumentation, plain, JSON serializable metadata DTO plugin owns as static data (host/catalog reads it, no runtime generation). H6 is reframed as generate/populate step: an extractor tool (outsideAuthKit.Plugins.Abstractions) reads the compiled plugin's C# XML doc and fillsPluginDocumentation, which the catalog serializes to JSON for catalog/docs/UI. H6 is not part of the runtime contract.Goal
Give every plugin single, serializable documentation shape the host and catalog can render without parsing prose READMEs, while keeping
IAuthKitPluginlean documentation is metadata plugin possesses, not runtime behavior it performs.Problem
namespace,type,method,property,parameter,exception,returns. Product documentation such as Overview, Setup, Configuration, Endpoints, Health, Security is different model. Mapping between them is not obvious and must not be guessed.GetDocumentation()as an executed method blurs two things: static plugin metadata vs runtime behavior. If the documentation is static, the API should read metadata, not generate a document.Status architecture decision
Two candidate models were considered:
and
Decision: documentation is static metadata you read, not behavior you execute. It is exposed as an accessor like property
PluginDocumentation Documentation { get; }— never method that generates anything. H6 is tooling the runtime contract exposes only the shape plus its default. Nothing in the DTO or the property performs generation.The binding condition:
Documentationbelongs onIAuthKitPluginonly if the host consumes it as runtime metadata a Plugin Catalog, Admin UI, or runtime discovery consuming/plugins/{id}-> JSON. If documentation is consumed only to generate a website, H5 does not exist in the runtime contract at all: the marker-driven H6 extractor alone is sufficient, producing static JSON/Markdown for the docs site.flowchart LR A["Plugin Assembly"] --> M["PluginManifest (what the plugin is)"] A --> D["Documentation source<br/>XML-doc + markers"] M --> C["Plugin Catalog"] D --> E["H6 Extractor"] E --> P["PluginDocumentation"] P --> C C --> J["JSON"] C --> U["UI"] C --> S["Docs"]Clean boundaries:
Scope
PluginDocumentationIAuthKitPluginAuthKit.Plugins.Abstractions(shape only) only if runtime catalog/admin consumes itPluginDocumentationProposed Contract (H5)
Documentationis property, not method, so the semantics are unambiguous:Documentationis metadata; an operation would beGetDocumentation(). IfGetDocumentation()is kept for API reasons, the ADR must state it is accessor like and performs no generation the property form is preferred.new()keeps every existing plugin compatible and valid.Parameters(MVP) is descriptive only: name -> short description of what the configuration entry means, never an actual value. If the catalog later needs structured rendering (Name,Description,Type,Required,Default), the model becomesPluginDocumentationParameter(Name, Description)as anIReadOnlyCollectiononly when real requirement demands it no abstraction now.XML doc -> Sections (H6) explicit, marker-driven mapping
XML doc describes code (types, members, parameters) product sections such as
Setup,Security,Configurationare different model. The extractor MUST NOT infer sections from class names, member lists, or parameter names.Rules:
[PluginDocumentationSection("...")]distinct from thePluginDocumentationDTO, so there is no name collision:/// <summary>Internal helper…</summary>must never enter plugin docs).<summary>,<remarks>, member docs) feeds the namedPluginDocumentationSection(Section, Content).Decisions
AuthKit.Plugins.Abstractions.PluginDocumentationis documentation DTO, not platform API: it holds plain records, strings, collections, and round trips to JSON with no runtime logic.Documentationstays onIAuthKitPluginonly for runtime consumption (catalog/admin//plugins/{id}). Pure static site generation needs no runtime API alone suffices.IAuthKitPluginis not home for every platform feature.Validation
PluginDocumentationserializes to and from JSON without loss.new()) is empty but valid; existing plugins compile unchanged.Documentationis a property (or documented accessor like method) that never generates at runtime.Parameterscontains descriptions only no runtime configuration values leak in.PluginDocumentationfrom explicitly marked XML doc unmarked code is ignored.Acceptance Criteria
new()default)DevTokens/DevToolscompile and load.Non Goals
Documentationis metadata access only.PluginDocumentation(descriptiveParametersonly)..Parametersabstraction beyond the MVP dictionary until real catalog requirement appears.AuthKit.Plugins.Abstractionstooling only.