From 0e3cdf3a6d799161c813fe5600fde192f7dc5e8e Mon Sep 17 00:00:00 2001 From: Provash Shoumma Date: Thu, 10 Sep 2026 13:24:51 +0200 Subject: [PATCH] docs: dedupe REST header requirements into a macro --- docs/specification/shopping/cart/rest.md | 12 +------- docs/specification/shopping/catalog/rest.md | 5 +--- docs/specification/shopping/checkout/rest.md | 12 +------- docs/specification/shopping/order/rest.md | 10 +------ main.py | 29 ++++++++++++++++++++ 5 files changed, 33 insertions(+), 35 deletions(-) diff --git a/docs/specification/shopping/cart/rest.md b/docs/specification/shopping/cart/rest.md index 9ad0f01bc..8f24c7b1b 100644 --- a/docs/specification/shopping/cart/rest.md +++ b/docs/specification/shopping/cart/rest.md @@ -475,17 +475,7 @@ operations unless otherwise noted. ### Specific Header Requirements -* **UCP-Agent**: All requests **MUST** include the `UCP-Agent` header - containing the platform profile URI using Dictionary Structured Field syntax - ([RFC 8941](https://datatracker.ietf.org/doc/html/rfc8941){target="_blank"}). - Format: `profile="https://platform.example/profile"`. -* **Idempotency-Key**: Operations that modify state **SHOULD** support - idempotency. When provided, the server **MUST**: - 1. Store the key with the operation result for at least 24 hours. - 2. Return the cached result for duplicate keys whose request body matches the original. - 3. Return `409 Conflict` if the key is reused with a mismatched body. - See [Message Signatures — Idempotency Key Requirements](../../signatures.md#replay-protection) - for the full payload-matching contract. +{{ header_requirements('ucp_agent', 'idempotency_key') }} ## Protocol Mechanics diff --git a/docs/specification/shopping/catalog/rest.md b/docs/specification/shopping/catalog/rest.md index f6cc59cb0..69a22e56d 100644 --- a/docs/specification/shopping/catalog/rest.md +++ b/docs/specification/shopping/catalog/rest.md @@ -518,10 +518,7 @@ operations unless otherwise noted. ### Specific Header Requirements -* **UCP-Agent**: All requests **MUST** include the `UCP-Agent` header - containing the platform profile URI using Dictionary Structured Field syntax - ([RFC 8941](https://datatracker.ietf.org/doc/html/rfc8941){target="_blank"}). - Format: `profile="https://platform.example/profile"`. +{{ header_requirements('ucp_agent') }} ## Error Handling diff --git a/docs/specification/shopping/checkout/rest.md b/docs/specification/shopping/checkout/rest.md index 1faa4e40f..764a699f1 100644 --- a/docs/specification/shopping/checkout/rest.md +++ b/docs/specification/shopping/checkout/rest.md @@ -1301,17 +1301,7 @@ operations unless otherwise noted. ### Specific Header Requirements -* **UCP-Agent**: All requests **MUST** include the `UCP-Agent` header - containing the platform profile URI using Dictionary Structured Field syntax - ([RFC 8941](https://datatracker.ietf.org/doc/html/rfc8941){target="_blank"}). - Format: `profile="https://platform.example/profile"`. -* **Idempotency-Key**: Operations that modify state **SHOULD** support - idempotency. When provided, the server **MUST**: - 1. Store the key with the operation result for at least 24 hours. - 2. Return the cached result for duplicate keys whose request body matches the original. - 3. Return `409 Conflict` if the key is reused with a mismatched body. - See [Message Signatures — Idempotency Key Requirements](../../signatures.md#replay-protection) - for the full payload-matching contract. +{{ header_requirements('ucp_agent', 'idempotency_key') }} ## Protocol Mechanics diff --git a/docs/specification/shopping/order/rest.md b/docs/specification/shopping/order/rest.md index fbd7e6120..4e40f82b9 100644 --- a/docs/specification/shopping/order/rest.md +++ b/docs/specification/shopping/order/rest.md @@ -231,15 +231,7 @@ Returns the current-state snapshot of an order. ### Specific Header Requirements -**UCP-Agent** (required on all requests): - -Platform identification using -[RFC 8941 Dictionary](https://www.rfc-editor.org/rfc/rfc8941#name-dictionaries){ target="_blank" } -syntax: - -```http -UCP-Agent: profile="https://platform.example/.well-known/ucp" -``` +{{ header_requirements('ucp_agent') }} ## Message Signing diff --git a/main.py b/main.py index 2d5d1309a..512fea2fa 100644 --- a/main.py +++ b/main.py @@ -1590,6 +1590,35 @@ def resolve_structure(schema, root): f"Error processing OpenAPI: {e}{get_error_context()}" ) from e + # --- Shared "Specific Header Requirements" prose --- + HEADER_REQUIREMENTS = { + "ucp_agent": ( + "* **UCP-Agent**: All requests **MUST** include the `UCP-Agent` header\n" + " containing the platform profile URI using Dictionary Structured Field syntax\n" + ' ([RFC 8941](https://datatracker.ietf.org/doc/html/rfc8941){target="_blank"}).\n' + ' Format: `profile="https://platform.example/profile"`.' + ), + "idempotency_key": ( + "* **Idempotency-Key**: Operations that modify state **SHOULD** support\n" + " idempotency. When provided, the server **MUST**:\n" + " 1. Store the key with the operation result for at least 24 hours.\n" + " 2. Return the cached result for duplicate keys whose request body matches the original.\n" + " 3. Return `409 Conflict` if the key is reused with a mismatched body.\n" + " See [Message Signatures — Idempotency Key Requirements](/specification/signatures/#replay-protection)\n" + " for the full payload-matching contract." + ), + } + + @env.macro + def header_requirements(*keys): + """Render shared 'Specific Header Requirements' bullets by key.""" + try: + return "\n".join(HEADER_REQUIREMENTS[k] for k in keys) + except KeyError as exc: + raise ValueError( + f"Unknown header requirement {exc}{get_error_context()}." + ) + # --- MACRO 4: For HTTP Headers --- @env.macro def header_fields(operation_id, file_name):