Skip to main content

policy-authoring

Conventions and patterns for creating policy authoring types in the Azure API Management policy toolkit. Use this skill when creating or modifying config records in src/Authoring/Configs/ or adding methods to section context interfaces.

ソース情報

リポジトリ
Azure/azure-api-management-policy-toolkit
ソースの最終更新活動
2026年3月8日 18:53
検出された SKILL.md の言語
英語
スター
95
フォーク
37

インストール方法

デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。

ソースファイルを確認

インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。

SKILL.md を表示中

SKILL.md
ソースの指示 · 読み取り専用プレビュー
name
policy-authoring
description
Conventions and patterns for creating policy authoring types in the Azure API Management policy toolkit. Use this skill when creating or modifying config records in src/Authoring/Configs/ or adding methods to section context interfaces.
# Policy Authoring Patterns This skill describes how to create authoring types (config records and context interface methods) for policies in the Azure API Management policy toolkit. ## Config Record — `src/Authoring/Configs/{PolicyName}Config.cs` ### File Template ```csharp // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. namespace Microsoft.Azure.ApiManagement.PolicyToolkit.Authoring; /// <summary> /// Configuration for the {xml-element-name} policy.<br/> /// {Brief description of what the policy does.} /// </summary> public record {PolicyName}Config { /// <summary> /// {Property description}. Policy expressions are allowed. /// </summary> [ExpressionAllowed] public required {Type} {PropertyName} { get; init; } /// <summary> /// Optional. {Property description}. /// </summary> public {Type}? {OptionalPropertyName} { get; init; } } ``` ### Related Attributes - **`[Document]`** (`src/Authoring/Attributes/DocumentAttribute.cs`) — Marks a class as a policy document. Optional `name` parameter; `Scope` and `Type` properties control document scope and type. - **`[Expression]`** (`src/Authoring/Attributes/ExpressionAttribute.cs`) — Marks a method as a policy expression (captures source file path via `[CallerFilePath]`). Used by the compiler to identify expression helper methods. - **`[ExpressionAllowed]`** (`src/Authoring/Attributes/ExpressionAllowedAttribute.cs`) — Marks config properties or parameters that accept policy expressions. ### Property Rules - **Required properties**: use the `required` keyword + `init` setter. - **Optional properties**: use a nullable type (`?`) + `init` setter. Do **not** use `required`. - **Expression-enabled properties**: decorate with `[ExpressionAllowed]` attribute. Add "Policy expressions are allowed." to the XML doc. - **Constrained properties** (enums, allowed values): use either: - A C# `enum` type (preferred for fixed, type-safe values) - A `string` property with XML doc listing allowed values (for values documented outside code) - Validation is applied at **compilation time** by the compiler class, **not at authoring time**. The config record accepts any value; the compiler reports diagnostics if invalid. - **Sub-configs** (child element arrays): define as separate `public record` types in the same file. - **Sub-config naming convention**: Use descriptive nouns that reflect their purpose (e.g., `ApiRateLimit`, `AddressRange`, `MatchCondition`), not generic names like `Item` or `Element`. - **Every public type and member** must have `/// <summary>` XML documentation covering: - Purpose - Required vs optional status - Default value (if any) - Expression support (yes/no) - Allowed values / enums (if applicable) ### Real Examples **Simple attributes with expression support** — `RateLimitByKeyConfig.cs`: ```csharp public record RateLimitByKeyConfig { [ExpressionAllowed] public required int Calls { get; init; } [ExpressionAllowed] public required int RenewalPeriod { get; init; } [ExpressionAllowed] public required string CounterKey { get; init; } [ExpressionAllowed] public bool? IncrementCondition { get; init; } public string? RetryAfterHeaderName { get; init; } } ``` **Nested sub-records** — `RateLimitConfig.cs`: ```csharp public record RateLimitConfig { public required int Calls { get; init; } public required int RenewalPeriod { get; init; } public string? RetryAfterHeaderName { get; init; } public ApiRateLimit[]? Apis { get; init; } } public record ApiRateLimit : EntityLimitConfig { public OperationRateLimit[]? Operations { get; init; } } public abstract record EntityLimitConfig { public string? Name { get; init; } public string? Id { get; init; } public required int Calls { get; init; } public required int RenewalPeriod { get; init; } } ``` **Typed child arrays** — `IpFilterConfig.cs`: ```csharp public record IpFilterConfig { /// <summary> /// The action to apply: 'allow' or 'deny'. Policy expressions are allowed. /// </summary> [ExpressionAllowed] public required string Action { get; init; } /// <summary> /// Optional. IP addresses. Policy expressions are allowed. /// </summary> [ExpressionAllowed] public string[]? Addresses { get; init; } /// <summary> /// Optional. IP address ranges. /// </summary> public AddressRange[]? AddressRanges { get; init; } } /// <summary> /// An IP address range with 'from' and 'to' octets. /// </summary> public record AddressRange { /// <summary> /// The starting IP address. Policy expressions are allowed. /// </summary> [ExpressionAllowed] public required string From { get; init; } /// <summary> /// The ending IP address. Policy expressions are allowed. /// </summary> [ExpressionAllowed] public required string To { get; init; } } ``` **Constrained values with enum** — `AdvancedPolicyConfig.cs` (example pattern): ```csharp /// <summary> /// The caching behavior for the policy action. /// </summary> public enum CachingBehavior { /// <summary>Cache the response.</summary> Store, /// <summary>Reuse a cached response if available.</summary> Validate, /// <summary>Bypass cache entirely.</summary> Bypass } public record AdvancedPolicyConfig { /// <summary> /// Required. The caching behavior: 'Store', 'Validate', or 'Bypass'. /// </summary> public required CachingBehavior Behavior { get; init; } } ``` ## Context Interface Methods Add method signatures to the appropriate section interfaces. Policies may appear in one or more sections: - `src/Authoring/IInboundContext.cs` - `src/Authoring/IOutboundContext.cs` - `src/Authoring/IBackendContext.cs` - `src/Authoring/IOnErrorContext.cs` - `src/Authoring/IFragmentContext.cs` ### Method Signature Template ```csharp /// <summary> /// {Description of the policy behavior}.<br/> /// Compiled to <a href="{documentation-url}">{xml-element-name}</a> policy. /// </summary> /// <param name="config"> /// Configuration for the {xml-element-name} policy. /// </param> void {MethodName}({PolicyName}Config config); ``` ### Rules - The method name is PascalCase and matches the config name minus the `Config` suffix (e.g., `RateLimit` for `RateLimitConfig`). - All section interfaces extend `IHaveExpressionContext`, giving access to `ExpressionContext`. - For parameters that are expressions (not config objects), use `[ExpressionAllowed]` on the parameter itself. - Some policies use direct parameters instead of a config object (e.g., `void SetMethod(string method)`). Use this pattern only for policies with 1–2 simple parameters and no optional fields. ### `IFragmentContext` Duplication `IFragmentContext` currently duplicates method signatures from the section-specific interfaces (see the `//TODO` comment at the top of the file). **Every time you add a policy method to any section interface, you must also add the same signature to `IFragmentContext.cs`.** Copy the exact same method signature verbatim. Do not attempt to refactor this pattern.
GitHubで見る