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):