This is an automated email from the ASF dual-hosted git repository.

Yilialinn pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git


The following commit(s) were added to refs/heads/master by this push:
     new f94b3c765 docs: clarify JWE and RAG plugin guidance (#13873)
f94b3c765 is described below

commit f94b3c76567574ffd11981cad2a8b025a0af3f4f
Author: Yilia Lin <[email protected]>
AuthorDate: Mon Aug 31 10:13:19 2026 +0800

    docs: clarify JWE and RAG plugin guidance (#13873)
---
 docs/en/latest/plugins/ai-rag.md      | 26 +++++++++---------
 docs/en/latest/plugins/jwe-decrypt.md | 50 +++++++++++++++++++++++------------
 2 files changed, 46 insertions(+), 30 deletions(-)

diff --git a/docs/en/latest/plugins/ai-rag.md b/docs/en/latest/plugins/ai-rag.md
index fe1130ddf..113ee2bb2 100644
--- a/docs/en/latest/plugins/ai-rag.md
+++ b/docs/en/latest/plugins/ai-rag.md
@@ -7,7 +7,7 @@ keywords:
   - ai-rag
   - AI
   - LLM
-description: The ai-rag Plugin enhances LLM outputs with Retrieval-Augmented 
Generation (RAG), efficiently retrieving relevant documents to improve accuracy 
and contextual relevance in responses.
+description: The ai-rag Plugin retrieves context with Azure OpenAI embeddings 
and Azure AI Search before an LLM request is proxied.
 ---
 
 <!--
@@ -38,9 +38,9 @@ import TabItem from '@theme/TabItem';
 
 ## Description
 
-The `ai-rag` Plugin provides Retrieval-Augmented Generation (RAG) capabilities 
with LLMs. It facilitates the efficient retrieval of relevant documents or 
information from external data sources, which are used to enhance the LLM 
responses, thereby improving the accuracy and contextual relevance of the 
generated outputs.
+The `ai-rag` Plugin implements the retrieval step of a Retrieval-Augmented 
Generation (RAG) request flow. It generates an embedding from the request, 
performs a vector search, adds the retrieved content to the protocol-specific 
LLM request input, and removes the `ai_rag` request object before the request 
is proxied.
 
-The Plugin supports using [Azure 
OpenAI](https://azure.microsoft.com/en-us/products/ai-services/openai-service) 
and [Azure AI 
Search](https://azure.microsoft.com/en-us/products/ai-services/ai-search) 
services for generating embeddings and performing vector search. PRs for 
introducing support for other service providers are welcomed.
+The current implementation supports [Azure 
OpenAI](https://azure.microsoft.com/en-us/products/ai-services/openai-service) 
for embeddings and [Azure AI 
Search](https://azure.microsoft.com/en-us/products/ai-services/ai-search) for 
vector search. Use the [`ai-proxy`](./ai-proxy.md) Plugin in the same request 
flow to proxy the augmented request to the LLM provider. The Plugin does not 
create or populate a search index; prepare the index and its content before 
sending requests through APISIX.
 
 ## Plugin Attributes
 
@@ -115,14 +115,14 @@ Save the API keys and endpoints to environment variables:
 ```shell
 # replace with your values
 
-AZ_OPENAI_DOMAIN=https://ai-plugin-developer.openai.azure.com
-AZ_OPENAI_API_KEY=9m7VYroxITMDEqKKEnpOknn1rV7QNQT7DrIBApcwMLYJQQJ99ALACYeBjFXJ3w3AAABACOGXGcd
+AZ_OPENAI_DOMAIN=https://your-openai-resource.openai.azure.com
+AZ_OPENAI_API_KEY=your-azure-openai-api-key
 
AZ_CHAT_ENDPOINT=${AZ_OPENAI_DOMAIN}/openai/deployments/gpt-4o/chat/completions?api-version=2024-02-15-preview
 AZ_EMBEDDING_MODEL=text-embedding-3-large
 
AZ_EMBEDDINGS_ENDPOINT=${AZ_OPENAI_DOMAIN}/openai/deployments/${AZ_EMBEDDING_MODEL}/embeddings?api-version=2023-05-15
 
-AZ_AI_SEARCH_SVC_DOMAIN=https://ai-plugin-developer.search.windows.net
-AZ_AI_SEARCH_KEY=IFZBp3fKVdq7loEVe9LdwMvVdZrad9A4lPH90AzSeC06SlR
+AZ_AI_SEARCH_SVC_DOMAIN=https://your-search-service.search.windows.net
+AZ_AI_SEARCH_KEY=your-azure-ai-search-api-key
 AZ_AI_SEARCH_INDEX=vectest
 
AZ_AI_SEARCH_ENDPOINT=${AZ_AI_SEARCH_SVC_DOMAIN}/indexes/${AZ_AI_SEARCH_INDEX}/docs/search?api-version=2024-07-01
 ```
@@ -243,17 +243,17 @@ spec:
         embeddings_provider:
           azure_openai:
             endpoint: 
"https://your-openai-resource.openai.azure.com/openai/deployments/text-embedding-3-large/embeddings?api-version=2023-05-15";
-            api_key: "Bearer your-api-key"
+            api_key: "your-azure-openai-api-key"
         vector_search_provider:
           azure_ai_search:
             endpoint: 
"https://your-search-service.search.windows.net/indexes/vectest/docs/search?api-version=2024-07-01";
-            api_key: "Bearer your-api-key"
+            api_key: "your-azure-ai-search-api-key"
     - name: ai-proxy
       config:
         provider: openai
         auth:
           header:
-            api-key: "Bearer your-api-key"
+            api-key: "your-azure-openai-api-key"
         model: gpt-4o
         override:
           endpoint: 
"https://your-openai-resource.openai.azure.com/openai/deployments/gpt-4o/chat/completions?api-version=2024-02-15-preview";
@@ -307,18 +307,18 @@ spec:
             embeddings_provider:
               azure_openai:
                 endpoint: 
"https://your-openai-resource.openai.azure.com/openai/deployments/text-embedding-3-large/embeddings?api-version=2023-05-15";
-                api_key: "Bearer your-api-key"
+                api_key: "your-azure-openai-api-key"
             vector_search_provider:
               azure_ai_search:
                 endpoint: 
"https://your-search-service.search.windows.net/indexes/vectest/docs/search?api-version=2024-07-01";
-                api_key: "Bearer your-api-key"
+                api_key: "your-azure-ai-search-api-key"
         - name: ai-proxy
           enable: true
           config:
             provider: openai
             auth:
               header:
-                api-key: "Bearer your-api-key"
+                api-key: "your-azure-openai-api-key"
             model: gpt-4o
             override:
               endpoint: 
"https://your-openai-resource.openai.azure.com/openai/deployments/gpt-4o/chat/completions?api-version=2024-02-15-preview";
diff --git a/docs/en/latest/plugins/jwe-decrypt.md 
b/docs/en/latest/plugins/jwe-decrypt.md
index 02dafc736..78a8947b3 100644
--- a/docs/en/latest/plugins/jwe-decrypt.md
+++ b/docs/en/latest/plugins/jwe-decrypt.md
@@ -6,7 +6,7 @@ keywords:
   - Plugin
   - JWE Decrypt
   - jwe-decrypt
-description: The jwe-decrypt Plugin decrypts JWE authorization headers in 
requests directed to Routes or Services, enhancing API security.
+description: The jwe-decrypt Plugin decrypts its supported five-part compact 
token format and forwards the plaintext in a configured request header.
 ---
 
 <!--
@@ -37,19 +37,31 @@ import TabItem from '@theme/TabItem';
 
 ## Description
 
-The `jwe-decrypt` Plugin decrypts 
[JWE](https://datatracker.ietf.org/doc/html/rfc7516) authorization headers in 
requests sent to APISIX [Routes](../terminology/route.md) or 
[Services](../terminology/service.md).
+The `jwe-decrypt` Plugin reads a five-part compact token from a request 
header, selects a [Consumer](../terminology/consumer.md) by the token's `kid`, 
decrypts the ciphertext with AES-256-GCM, and writes the plaintext to a 
configured header before proxying the request. You can enable the Plugin on 
APISIX [Routes](../terminology/route.md) or 
[Services](../terminology/service.md).
 
-The decryption key should be configured in 
[Consumer](../terminology/consumer.md).
+The token resembles [JWE Compact 
Serialization](https://datatracker.ietf.org/doc/html/rfc7516#section-3.1), but 
the current Plugin uses a Plugin-specific format. Configure a 32-byte 
decryption secret on the Consumer.
+
+:::warning
+
+The current implementation reads `kid` from the decoded header but does not 
validate the `alg` or `enc` fields and does not use the protected-header 
segment as AES-GCM additional authenticated data (AAD). Standard RFC 7516 JWE 
libraries are therefore not directly interoperable. Generate tokens with the 
exact format described below, use a fixed trusted token generator, and do not 
treat header fields as authenticated.
+
+:::
+
+:::caution
+
+The decrypted plaintext is forwarded in a request header. For sensitive 
plaintext, do not rely on an HTTPS Upstream alone: APISIX does not verify 
server certificates for standard HTTP Upstreams. Send the request over an 
authenticated, protected network path, such as through a proxy or service mesh 
that validates the upstream server's identity. Restrict access to the upstream 
and avoid logging the configured forwarding header.
+
+:::
 
 ## Attributes
 
 ### Consumer
 
-| Name              | Type    | Required | Default | Valid values   | 
Description                                                                     
                                                                                
                                                                         |
-| ----------------- | ------- | -------- | ------- | -------------- | 
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 |
-| key               | string  | True     |         |                | A unique 
key that identifies the Credential for a Consumer.                              
                                                                                
                                                                |
-| secret            | string  | True     |         | 32 characters  | The 
shared symmetric encryption/decryption key. You can also store it in an 
environment variable and reference it using the `env://` prefix, or in a secret 
manager such as HashiCorp Vault's KV secrets engine, and reference it using the 
`secret://` prefix. |
-| is_base64_encoded | boolean | False    | false   |                | Set to 
true if the secret is base64 encoded. Note that after enabling 
`is_base64_encoded`, the `secret` length may exceed 32 characters. You only 
need to make sure the decoded length is still 32 characters.                    
   |
+| Name              | Type    | Required | Default | Valid values   | 
Description                                                                     
                                                         |
+| ----------------- | ------- | -------- | ------- | -------------- | 
----------------------------------------------------------------------------------------------------------------------------------------
 |
+| key               | string  | True     |         |                | A unique 
key that identifies the Credential for a Consumer.                              
                                                |
+| secret            | string  | True     |         | 32 bytes       | A shared 
symmetric key. Use a [secret reference](../terminology/secret.md), such as 
`$env://...` or `$secret://...`.                     |
+| is_base64_encoded | boolean | False    | false   |                | Set to 
true if the secret is base64url encoded. The decoded secret must still be 32 
bytes.                                               |
 
 ### Route or Service
 
@@ -57,7 +69,7 @@ The decryption key should be configured in 
[Consumer](../terminology/consumer.md
 | -------------- | ------- | -------- | ------------- | ------------ | 
---------------------------------------------------------------------------------------------------------------------------------
 |
 | header         | string  | True     | Authorization |              | The 
header to get the token from.                                                   
                                              |
 | forward_header | string  | True     | Authorization |              | Name of 
the header that passes the plaintext to the Upstream.                           
                                          |
-| strict         | boolean | False    | true          |              | If 
true, throw a 403 error if JWE token is missing from the request. If false, do 
not throw an error when JWE token is not found. |
+| strict         | boolean | False    | true          |              | If 
true, return a 403 error when the encrypted plugin token is missing. If false, 
continue when the token is not found.           |
 
 ## Examples
 
@@ -75,7 +87,7 @@ admin_key=$(yq '.deployment.admin.admin_key[0].key' 
conf/config.yaml | sed 's/"/
 
 ### Create a Consumer with the Decryption Key
 
-The following example demonstrates how to create a Consumer with the 
decryption key and generate a JWE token for it.
+The following example demonstrates how to create a Consumer with the 
decryption key and generate an encrypted plugin token for it.
 
 Create a Consumer with `jwe-decrypt` and configure the decryption key:
 
@@ -160,13 +172,13 @@ kubectl apply -f jwe-consumer-ic.yaml
 </TabItem>
 </Tabs>
 
-To generate a JWE token for the Consumer, encrypt the payload offline with any 
AES-256-GCM library, using the Consumer secret as the key. The token structure 
is:
+To generate a token for the Consumer, encrypt the payload offline with 
AES-256-GCM without protected-header AAD, using the Consumer secret as the key. 
Standard RFC 7516 libraries normally authenticate the protected header as AAD 
and are not directly interoperable with this Plugin. Use the following exact 
token structure:
 
 ```text
 base64url(header).<empty>.base64url(iv).base64url(ciphertext).base64url(tag)
 ```
 
-where the header is `{"alg":"dir","enc":"A256GCM","kid":"<consumer-key>"}`. 
The IV must be unique and randomly generated for every token; never reuse an IV 
with the same key.
+where the header is `{"alg":"dir","enc":"A256GCM","kid":"<consumer-key>"}`. 
The fields describe the intended algorithm and identify the Consumer, but the 
current Plugin does not authenticate or validate them. The IV must be unique 
and randomly generated for every token; never reuse an IV with the same key.
 
 For example, the following token encrypts the payload 
`{"uid":10000,"uname":"test"}` for the Consumer key `jack-key` with the secret 
configured above:
 
@@ -174,9 +186,9 @@ For example, the following token encrypts the payload 
`{"uid":10000,"uname":"tes
 
eyJraWQiOiJqYWNrLWtleSIsImFsZyI6ImRpciIsImVuYyI6IkEyNTZHQ00ifQ..vi29KBCQKcVmPwTT.VToyPMFbq-ZY05MIpntP1N3AmYeq3zELQ0B6iQ.vuTPG2ODc-DjUTjNCzfA2A
 ```
 
-### Decrypt Data with JWE
+### Decrypt Data from the Plugin Token
 
-The following example demonstrates how to decrypt the JWE token generated 
above.
+The following example demonstrates how to decrypt the plugin token generated 
above.
 
 Create a Route with `jwe-decrypt` to decrypt the authorization header:
 
@@ -197,8 +209,9 @@ curl "http://127.0.0.1:9180/apisix/admin/routes"; -X PUT \
     },
     "upstream": {
       "type": "roundrobin",
+      "scheme": "https",
       "nodes": {
-        "httpbin.org:80": 1
+        "httpbin.org:443": 1
       }
     }
   }'
@@ -221,9 +234,10 @@ services:
             forward_header: Authorization
     upstream:
       type: roundrobin
+      scheme: https
       nodes:
         - host: httpbin.org
-          port: 80
+          port: 443
           weight: 1
 ```
 
@@ -240,6 +254,8 @@ adc sync -f adc.yaml
 <Tabs groupId="k8s-api">
 <TabItem value="gateway-api" label="Gateway API">
 
+The following Gateway API configuration uses public HTTPBin only with the 
non-sensitive demonstration payload shown on this page. Before forwarding real 
decrypted data, replace it with a controlled upstream and use an authenticated, 
protected network path. An APISIX HTTPS Upstream does not validate the upstream 
server certificate by itself; use a proxy or service mesh that validates the 
upstream server's identity.
+
 ```yaml title="jwe-decrypt-ic.yaml"
 apiVersion: v1
 kind: Service
@@ -304,7 +320,7 @@ kubectl apply -f jwe-decrypt-ic.yaml
 </TabItem>
 </Tabs>
 
-Send a request to the Route with the JWE encrypted data in the `Authorization` 
header:
+Send a request to the Route with the encrypted plugin token in the 
`Authorization` header:
 
 ```shell
 curl "http://127.0.0.1:9080/anything/jwe"; -H 'Authorization: 
eyJraWQiOiJqYWNrLWtleSIsImFsZyI6ImRpciIsImVuYyI6IkEyNTZHQ00ifQ..vi29KBCQKcVmPwTT.VToyPMFbq-ZY05MIpntP1N3AmYeq3zELQ0B6iQ.vuTPG2ODc-DjUTjNCzfA2A'

Reply via email to