diff --git a/CLAUDE.md b/CLAUDE.md index 2d114884..fb442fac 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -121,6 +121,29 @@ This repo reads its config from etcd, but users never write etcd directly — th - Exactly four divergence axes are registered as intentional and allowed: reference style (names here vs UUIDs in the CP), tenancy scoping (flat here vs org/environment there), credential custody (`key_hash` in documents here vs server-generated plaintext-once there), and CP-derived fields (`cost`, `telemetry_tags`). Anything else that diverges from cp-admin.yaml is drift — the planned cross-plane contract check will fail it. - Why the CP spec and not this repo's schemas: the CP is spec-first behind a closed validator (its spec already is the authoritative field shape on that side), the spec renders into the customer-facing API reference, and this repo's schemas are generated from the implementation — a schema that follows the implementation cannot lead it. Naming drift has already cost real churn: #644 (the generated schema advertised `rps`/`rph` the validator rejected) and #657 (a wire-breaking rename because the field was named DP-first). +## AISIX Product Terminology + +Use the following terms in public prose, generated API descriptions, release +notes, and configuration comments: + +- **AISIX AI Gateway** is the open-source product. Use **open-source AISIX + gateway** when the distinction from AISIX Cloud matters; after establishing + the product, use **AISIX gateway** or **gateway**. +- **AISIX Cloud** is the commercial product umbrella. **Hybrid Cloud** is its + API7-hosted control-plane option, and **On-Premises** is its customer-hosted + control-plane option. Do not present **AISIX Hybrid Cloud** or **AISIX + On-Premises** as separate products. +- An AISIX gateway is a **data plane** only within AISIX Cloud architecture. Do + not call an independently operated open-source gateway a data plane. +- Do not use **standalone gateway** as a product label. `standalone mode` and + `managed mode` remain valid when describing runtime behavior. +- Avoid unqualified **self-hosted**. Name the component being operated, such as + the open-source AISIX gateway, the On-Premises control plane, or a self-hosted + upstream service. +- The Dashboard is the control plane's user interface, not the whole control + plane. Live AI requests pass through the gateway directly and do not pass + through the AISIX Cloud control plane or API7. + ## Documentation Lives in api7/docs **User-facing documentation is maintained in the `api7/docs` repository (published to ), not in this repo.** diff --git a/Dockerfile b/Dockerfile index fcd740dd..509e90dc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,13 +17,18 @@ # docker run --rm -v $(pwd)/config.example.yaml:/etc/aisix/config.yaml \ # aisix:dev # -# Run, managed (aisix.cloud tenant — bake config + env-var overrides): +# Run, managed (connected to AISIX Cloud with env-var overrides): # docker run --rm \ # -e AISIX_CONFIG_PATH=/etc/aisix/config.managed.yaml \ -# -e AISIX_MANAGED__REGISTRATION_TOKEN=$DEPLOYMENT_TOKEN \ -# -e AISIX_MANAGED__CP_BASE_URL=https://api.us.aisix.cloud \ +# -e AISIX_MANAGED__CP_BASE_URL \ +# -e AISIX_MANAGED__CP_ETCD_ENDPOINT \ +# -e AISIX_MANAGED__CP_CERT_PEM \ +# -e AISIX_MANAGED__CP_KEY_PEM \ +# -e AISIX_MANAGED__CP_CA_PEM \ # -v aisix-mtls:/var/lib/aisix \ # aisix:dev +# The volume preserves the materialized mTLS bundle and gateway identity across +# container restarts. # --- Stage 1: build ---------------------------------------------------------- FROM rust:1.93-bookworm AS builder @@ -98,9 +103,10 @@ RUN --mount=type=bind,from=builder,source=/usr/local/bin/aisix,target=/mnt/aisix && apt-get purge -y --auto-remove libcap2-bin \ && rm -rf /var/lib/apt/lists/* -# Bake the managed-mode bootstrap config so aisix.cloud tenants can -# `docker run` without mounting anything — env vars carry the per-DP -# secret bits (registration token + CP base URL). +# Bake the managed-mode bootstrap config so AISIX gateways managed by +# AISIX Cloud can `docker run` without mounting a configuration file. +# Environment variables provide the control-plane endpoints and gateway mTLS +# certificate bundle. COPY config.managed.yaml /etc/aisix/config.managed.yaml # Entrypoint script picks the config file via AISIX_CONFIG_PATH so the diff --git a/README.md b/README.md index fd46faad..9d594dcc 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,8 @@ **One OpenAI-compatible API in front of every model.** Route, govern, secure, cache, and observe all your LLM and AI-agent traffic from a single control point — shipped as one -static binary with low per-request overhead. Self-host for free, forever. +static binary with low per-request overhead. Run it in your infrastructure for free, +forever. *Built by the original creators of [Apache APISIX](https://apisix.apache.org/).* @@ -38,16 +39,19 @@ overhead. It runs as a **single static binary** — low cold-start, lock-free config reads, and hot configuration reloads with no restarts: declare resources in one `resources.yaml` and -reload on `SIGHUP`, or point the gateway at etcd for a multi-replica cluster. Run it **self-hosted and free**, or connect it to +reload on `SIGHUP`, or point the gateway at etcd for a multi-replica cluster. Run the +open-source gateway in your infrastructure, or connect it to **[AISIX Cloud](https://api7.ai/ai-gateway?utm_source=github&utm_medium=readme&utm_campaign=cloud)** -for a managed control plane with team governance, budgets, audit, and a dashboard. - -> **AISIX AI Gateway (this repo)** is the open-source core — the gateway, i.e. the data -> plane. **[AISIX Cloud](https://api7.ai/ai-gateway?utm_source=github&utm_medium=readme&utm_campaign=cloud)** -> adds a managed control plane on top, either operated by API7 (**Hybrid Cloud**) or run -> entirely in your own infrastructure (**On-Premises**). In every form the gateway runs in -> your environment and calls providers directly — live AI traffic never leaves your -> infrastructure. The proxy API is identical throughout. +for centralized management with team governance, budgets, audit, and a dashboard. + +> **AISIX AI Gateway (this repo)** is the open-source product. It runs without a control +> plane using declarative configuration or etcd. When connected to +> **[AISIX Cloud](https://api7.ai/ai-gateway?utm_source=github&utm_medium=readme&utm_campaign=cloud)**, +> the same gateway serves as the data plane. AISIX Cloud adds a commercial control plane, +> either hosted by API7 (**Hybrid Cloud**) or hosted by you in your infrastructure +> (**On-Premises**). In both options, the gateway runs in your environment and calls +> providers directly; live AI traffic does not pass through the control plane or API7. +> The proxy API is identical throughout. > **[Talk to us about AISIX Cloud →](https://api7.ai/contact?utm_source=github&utm_medium=readme&utm_campaign=cloud)** ## ⚡ Quickstart @@ -131,8 +135,9 @@ For a multi-replica cluster, point the gateway at etcd instead — `resources_fi one `base_url` and switch models without changing code. - **A real gateway, in Rust.** Single static binary, low cold-start, lock-free config reads on the hot path, native streaming. -- **Open-source core, free forever.** Apache-2.0, self-hostable end to end. Reach for - AISIX Cloud only when you want the managed control plane. +- **Open source, free forever.** Apache-2.0 licensed and built to run in your + infrastructure. Choose AISIX Cloud when you want centralized management through a + control plane and dashboard. - **Production controls built in.** Routing & failover, rate limits, guardrails, caching, and observability ship in the box. (Budgets and spend caps are an AISIX Cloud feature — the gateway enforces the control plane's decisions.) @@ -206,7 +211,7 @@ OpenAI-shaped. | Adapter family | Reaches | Wire shape · auth | |---|---|---| -| `openai` | OpenAI **+ any OpenAI-compatible vendor** — DeepSeek, Groq, Mistral, Together, Fireworks, Perplexity, vLLM, Ollama, self-hosted | OpenAI chat completions · Bearer | +| `openai` | OpenAI **+ any OpenAI-compatible vendor** — DeepSeek, Groq, Mistral, Together, Fireworks, Perplexity, vLLM, Ollama, or self-hosted OpenAI-compatible endpoints | OpenAI chat completions · Bearer | | `anthropic` | Anthropic Claude | Anthropic Messages · `x-api-key` | | `bedrock` | AWS Bedrock — Anthropic, Meta Llama, Mistral, Cohere, Amazon Titan/Nova, AI21 | Bedrock Converse + `/invoke` · SigV4 | | `vertex` | Google Vertex AI (Gemini) | Vertex `:generateContent` · OAuth2 | @@ -219,8 +224,8 @@ Plus specialized handling for vendor quirks (e.g. DeepSeek reasoning content) an ## ☁️ Open source vs AISIX Cloud Same gateway binary, same proxy API — in every form the gateway runs in your environment. -**AISIX Cloud** adds a managed control plane on top, either operated by API7 -(**Hybrid Cloud**) or running entirely in your infrastructure (**On-Premises**). +**AISIX Cloud** adds a commercial control plane, either hosted by API7 +(**Hybrid Cloud**) or hosted in your infrastructure (**On-Premises**). @@ -266,7 +271,7 @@ Same gateway binary, same proxy API — in every form the gateway runs in your e | Usage & cost | Export logs, metrics, and usage events yourself | Managed usage views, model pricing catalog, spend reporting | | Surface | Status endpoints, OpenAPI read surface, playground | Full dashboard + per-environment playground | -→ **Want the managed control plane, governance, budgets, and dashboard?** +→ **Want the AISIX Cloud control plane, governance, budgets, and dashboard?** **[Talk to API7](https://api7.ai/contact?utm_source=github&utm_medium=readme&utm_campaign=cloud)** about Hybrid Cloud or On-Premises, or **[book a demo](https://api7.ai/contact?utm_source=github&utm_medium=readme&utm_campaign=demo)**. diff --git a/RELEASING.md b/RELEASING.md index 8ff3b68f..2c0d28d2 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -1,8 +1,9 @@ # Releasing -How an AISIX data-plane release is cut. Order matters: downstream packaging -(AISIX Cloud and the self-hosted bundle) pins the exact data-plane image -version, so the data plane is always tagged and published **first**. +How an AISIX AI Gateway release is cut. Order matters: downstream packaging +(AISIX Cloud and the On-Premises package, whose artifact name is +`aisix-self-hosted`) pins the exact gateway image version, so the gateway is +always tagged and published **first**. ## 1. Tag @@ -22,7 +23,7 @@ Pushing the tag triggers two workflows: - **`release-draft.yml`** creates a **draft** GitHub Release for the tag. The draft already leads with a version-stamped **Get started + Download** header (from [`.github/release-notes-header.md`](.github/release-notes-header.md): - docs, self-hosted quickstart, and the `docker pull` command), then a commented + docs, gateway quickstart, and the `docker pull` command), then a commented curated-notes scaffold to fill in, then GitHub's auto-generated **What's Changed** list as a starting skeleton. @@ -59,5 +60,6 @@ version for patch releases. ## 4. Downstream Only after the images are published, downstream release flows (AISIX Cloud / -the self-hosted package) may tag the same `vX.Y.Z` — their packaging pulls +the On-Premises package named `aisix-self-hosted`) may tag the same `vX.Y.Z` — +their packaging pulls `docker.io/api7/aisix:X.Y.Z` and fails if it does not exist yet. diff --git a/ROADMAP.md b/ROADMAP.md index 9dc19284..8b5ca480 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -10,7 +10,7 @@ For what the gateway does today — including [semantic routing](https://docs.ap - **Next** — planned after the current focus. - **Later** — on the longer-term horizon. -The **Surface** column shows where a capability lands: **Gateway** is the AISIX AI Gateway data plane; **Cloud** is the AISIX Cloud control plane and dashboard. +The **Surface** column shows where a capability lands: **Gateway** is the AISIX AI Gateway runtime; **Cloud** is the AISIX Cloud control plane and dashboard. ## Now @@ -30,7 +30,7 @@ The **Surface** column shows where a capability lands: **Gateway** is the AISIX | Conditional and wildcard routing | Route on request metadata, headers, and tags, and match upstreams by wildcard names such as `provider/*`. | Gateway | | Prompt management | Store, version, and reuse prompt templates with variables, resolved at the gateway. | Gateway · Cloud | | Caller key rotation experience | Self-service key rotation in the dashboard, plus scheduled auto-rotation with a grace overlap. | Cloud | -| Production-path playground | Run the Cloud playground through the managed data plane so it reflects real routing, caching, guardrails, and rate limiting. | Cloud | +| Production-path playground | Run the Cloud playground through a connected AISIX gateway so it reflects real routing, caching, guardrails, and rate limiting. | Cloud | | Cross-provider endpoint parity | Consistent embeddings, image generation, and Responses behavior across more providers. | Gateway | ## Later diff --git a/config.example.yaml b/config.example.yaml index c4e8e09c..e4a69da3 100644 --- a/config.example.yaml +++ b/config.example.yaml @@ -10,7 +10,7 @@ etcd: dial_timeout_ms: 5000 request_timeout_ms: 5000 # Optional TLS / mTLS bundle. Required when connecting to an - # aisix.cloud DP Manager (endpoint is https:// and the CP issues + # AISIX Cloud Data Plane Manager (endpoint is https:// and the control plane issues # a client cert via IssueAIDataplaneCertificate). Uncomment and # point to your mTLS bundle. # tls: @@ -134,10 +134,10 @@ observability: endpoint: "http://127.0.0.1:4317" sample_ratio: 1.0 -# Managed-mode switch. Uncomment when running as an aisix.cloud -# tenant: the admin API and Playground will NOT be bound — all +# Managed-mode switch. Uncomment when connecting the gateway to +# AISIX Cloud: the admin API and Playground will NOT be bound — all # configuration flows from etcd via the mTLS channel above, driven -# by the aisix.cloud control plane. +# by the AISIX Cloud control plane. # managed: # enabled: true diff --git a/config.managed.yaml b/config.managed.yaml index cd7311ab..6d49ae40 100644 --- a/config.managed.yaml +++ b/config.managed.yaml @@ -1,9 +1,10 @@ -# aisix — managed-mode bootstrap config (aisix.cloud tenant). +# AISIX gateway — managed-mode bootstrap configuration for AISIX Cloud. # -# Used by the official Docker image as `/etc/aisix/config.yaml`. +# Baked into the official Docker image as `/etc/aisix/config.managed.yaml`. +# Select it by setting `AISIX_CONFIG_PATH` to that path. # Only the bare minimum is set here: # -# - `managed.enabled: true` always on for this image +# - `managed.enabled: true` always on in this bootstrap configuration # - `etcd.endpoints: [placeholder]` overridden at boot from managed # CP endpoint config # - `admin.admin_keys: [placeholder]` validation requires the slot, diff --git a/crates/aisix-admin/src/openapi.rs b/crates/aisix-admin/src/openapi.rs index f30c9c53..a3853a38 100644 --- a/crates/aisix-admin/src/openapi.rs +++ b/crates/aisix-admin/src/openapi.rs @@ -38,7 +38,7 @@ const OPENAPI_JSON_BASE: &str = r##"{ "info": { "title": "AISIX Admin API", "version": "dev", - "description": "The AISIX Admin API is the self-hosted management interface for configuring the gateway at runtime. Use it when you operate AISIX directly and need to create or update models, caller API keys, provider credentials, guardrails, cache policies, and observability exporters.\n\nThe write endpoints (POST, PUT, DELETE) are deprecated in favor of declarative configuration: load resources from a `resources_file` (`resources.yaml`) or write them to etcd directly. Write endpoints remain functional, and every mutating response carries a `Deprecation` header (RFC 9745) plus a `Link` header with `rel=\"deprecation\"` pointing at the migration documentation. Read endpoints are not deprecated.\n\nManaged deployments do not expose this listener. Configure managed gateways through the AISIX managed control plane." + "description": "The AISIX Admin API configures an open-source AISIX gateway at runtime. Use it when you operate the gateway directly and need to create or update models, caller API keys, provider credentials, guardrails, cache policies, and observability exporters.\n\nThe write endpoints (POST, PUT, DELETE) are deprecated in favor of declarative configuration: load resources from a `resources_file` (`resources.yaml`) or write them to etcd directly. Write endpoints remain functional, and every mutating response carries a `Deprecation` header (RFC 9745) plus a `Link` header with `rel=\"deprecation\"` pointing at the migration documentation. Read endpoints are not deprecated.\n\nGateways connected to AISIX Cloud do not expose this listener. Configure them through AISIX Cloud." }, "paths": { "/livez": { @@ -3947,7 +3947,7 @@ const OPENAPI_JSON_BASE: &str = r##"{ } }, "additionalProperties": false, - "description": "Self-hosted Admin API request body for creating or updating a caller API key. Ownership fields supplied by the managed control plane are not accepted by this API." + "description": "AISIX Admin API request body for creating or updating a caller API key on an open-source AISIX gateway. Ownership fields supplied by AISIX Cloud are not accepted by this API." } } }, @@ -4853,7 +4853,7 @@ mod tests { } #[tokio::test] - async fn openapi_uses_self_hosted_apikey_request_schema() { + async fn openapi_uses_open_source_gateway_apikey_request_schema() { let parsed: serde_json::Value = serde_json::from_str(merged_openapi()).expect("merged_openapi must parse"); for (path, method) in [ @@ -4866,7 +4866,7 @@ mod tests { parsed["paths"][path][method]["requestBody"]["content"]["application/json"] ["schema"]["$ref"], "#/components/schemas/ApiKeyRequest", - "{method} {path} should document the self-hosted Admin API request body" + "{method} {path} should document the open-source gateway Admin API request body" ); } @@ -4875,33 +4875,33 @@ mod tests { assert_eq!(request["required"][1], "allowed_models"); assert!( request["properties"].get("allowed_tools").is_some(), - "self-hosted API key requests must document MCP tool access" + "open-source gateway API key requests must document MCP tool access" ); let request_allowed_tools = request["properties"]["allowed_tools"]["description"] .as_str() .unwrap(); assert!( request_allowed_tools.contains("omitted, set to `null`, or set to an empty list"), - "self-hosted API key request schema must document no-access tool-list behavior" + "open-source gateway API key request schema must document no-access tool-list behavior" ); assert!( request_allowed_tools.contains("__*"), - "self-hosted API key request schema must document the per-server wildcard" + "open-source gateway API key request schema must document the per-server wildcard" ); assert!( request["properties"].get("allowed_agents").is_some(), - "self-hosted API key requests must document A2A agent access" + "open-source gateway API key requests must document A2A agent access" ); let request_allowed_agents = request["properties"]["allowed_agents"]["description"] .as_str() .unwrap(); assert!( request_allowed_agents.contains("omitted, set to `null`, or set to an empty list"), - "self-hosted API key request schema must document no-access agent-list behavior" + "open-source gateway API key request schema must document no-access agent-list behavior" ); assert!( request_allowed_agents.contains("grants every agent"), - "self-hosted API key request schema must document wildcard agent access" + "open-source gateway API key request schema must document wildcard agent access" ); let public = &parsed["components"]["schemas"]["PublicApiKey"]; assert!( diff --git a/crates/aisix-core/src/config.rs b/crates/aisix-core/src/config.rs index 89bde457..4eecc99c 100644 --- a/crates/aisix-core/src/config.rs +++ b/crates/aisix-core/src/config.rs @@ -2226,6 +2226,80 @@ observability: assert_eq!(cfg.admin.addr, "127.0.0.1:0"); } + #[test] + fn managed_container_examples_use_supported_bootstrap_env() { + const CHILD_MARKER: &str = "TEST_MANAGED_CONFIG_ENV_CHILD"; + const MANAGED_ENV_VARS: [&str; 5] = [ + "AISIX_MANAGED__CP_BASE_URL", + "AISIX_MANAGED__CP_ETCD_ENDPOINT", + "AISIX_MANAGED__CP_CERT_PEM", + "AISIX_MANAGED__CP_KEY_PEM", + "AISIX_MANAGED__CP_CA_PEM", + ]; + + if std::env::var_os(CHILD_MARKER).is_none() { + let repo_root = Path::new(env!("CARGO_MANIFEST_DIR")).join("../.."); + for relative in ["Dockerfile", "docker/entrypoint.sh"] { + let example = std::fs::read_to_string(repo_root.join(relative)).unwrap(); + for variable in MANAGED_ENV_VARS { + assert!( + example.contains(variable), + "{relative} must document {variable}", + ); + } + assert!( + !example.contains("AISIX_MANAGED__REGISTRATION_TOKEN"), + "{relative} must not document the removed registration-token bootstrap", + ); + } + + // Isolate environment-backed loading in a child test process so + // concurrent tests cannot observe or overwrite these variables. + let mut child = std::process::Command::new(std::env::current_exe().unwrap()); + child + .arg("managed_container_examples_use_supported_bootstrap_env") + .arg("--test-threads=1") + .env(CHILD_MARKER, "1"); + for (key, _) in std::env::vars_os() { + if key.to_string_lossy().starts_with("AISIX_") { + child.env_remove(key); + } + } + child + .env(MANAGED_ENV_VARS[0], "https://cp.example.com/api") + .env(MANAGED_ENV_VARS[1], "etcd.example.com:7943") + .env(MANAGED_ENV_VARS[2], "test certificate") + .env(MANAGED_ENV_VARS[3], "test private key") + .env(MANAGED_ENV_VARS[4], "test CA certificate"); + let output = child.output().unwrap(); + assert!( + output.status.success(), + "child config test failed: {}", + String::from_utf8_lossy(&output.stderr), + ); + assert!( + String::from_utf8_lossy(&output.stdout).contains("1 passed"), + "child config test did not run exactly one passing test: {}", + String::from_utf8_lossy(&output.stdout), + ); + return; + } + + let path = concat!(env!("CARGO_MANIFEST_DIR"), "/../../config.managed.yaml"); + let cfg = Config::load_from_path(Some(Path::new(path))) + .expect("documented managed-mode environment variables must load"); + assert!(cfg.managed.is_managed()); + assert_eq!( + cfg.managed.cp_base_url.as_deref(), + Some("https://cp.example.com/api") + ); + assert_eq!( + cfg.managed.cp_etcd_endpoint.as_deref(), + Some("etcd.example.com:7943") + ); + assert!(cfg.managed.cert_bundle_provided()); + } + #[test] fn shipped_example_config_binds_the_metrics_listener() { // `config.example.yaml` is the self-hosted reference shape; pin diff --git a/crates/aisix-core/src/models/guardrail.rs b/crates/aisix-core/src/models/guardrail.rs index 849bb53d..3a2ca612 100644 --- a/crates/aisix-core/src/models/guardrail.rs +++ b/crates/aisix-core/src/models/guardrail.rs @@ -93,9 +93,8 @@ pub enum BedrockAWSCredentials { /// AWS access key ID for static Bedrock guardrail credentials. #[schemars(length(min = 1))] access_key_id: String, - /// Decrypted before projection. Plaintext is held in memory only - /// and is not logged. The data plane passes it to the - /// AWS SDK's static credentials provider. + /// AWS secret access key used to authenticate requests to Amazon + /// Bedrock. The gateway does not log the plaintext value. #[schemars(length(min = 1))] secret_access_key: String, }, @@ -127,7 +126,7 @@ pub enum BedrockLatencyMode { pub struct AzureContentSafetyConfig { /// Azure Cognitive Services resource endpoint, e.g. /// `https://my-resource.cognitiveservices.azure.com`. - /// The data plane appends `/contentsafety/text:shieldPrompt?api-version=2024-09-01`. + /// The gateway appends `/contentsafety/text:shieldPrompt?api-version=2024-09-01`. #[schemars(length(min = 1))] pub endpoint: String, /// Azure subscription key sent with the `Ocp-Apim-Subscription-Key` header. Decrypted before @@ -161,7 +160,7 @@ fn default_acs_timeout_ms() -> u32 { #[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema, PartialEq, Eq)] #[serde(deny_unknown_fields)] pub struct AzureContentSafetyTextModerationConfig { - /// Azure Cognitive Services resource endpoint. The data plane appends + /// Azure Cognitive Services resource endpoint. The gateway appends /// `/contentsafety/text:analyze?api-version=2024-09-01`. #[schemars(length(min = 1))] pub endpoint: String, @@ -285,7 +284,7 @@ fn default_acs_on_buffer_exceeded() -> String { #[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema, PartialEq, Eq)] #[serde(deny_unknown_fields)] pub struct AliyunTextModerationConfig { - /// Aliyun region the guardrail lives in, e.g. `cn-shanghai`. The data plane + /// Aliyun region the guardrail lives in, e.g. `cn-shanghai`. The gateway /// builds the endpoint `https://green-cip..aliyuncs.com`. #[schemars(length(min = 1))] pub region: String, @@ -364,7 +363,7 @@ fn default_aliyun_risk_level_threshold() -> String { #[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema, PartialEq, Eq)] #[serde(deny_unknown_fields)] pub struct AliyunAiGuardrailConfig { - /// Aliyun region the guardrail lives in, e.g. `cn-shanghai`. The data plane + /// Aliyun region the guardrail lives in, e.g. `cn-shanghai`. The gateway /// builds the endpoint `https://green-cip..aliyuncs.com`. #[schemars(length(min = 1))] pub region: String, @@ -547,7 +546,7 @@ pub struct LakeraConfig { #[schemars(length(min = 1))] pub api_key: String, /// Endpoint override, e.g. a regional or self-hosted Lakera deployment. - /// The data plane appends `/v2/guard`. Defaults to `https://api.lakera.ai`. + /// The gateway appends `/v2/guard`. Defaults to `https://api.lakera.ai`. #[serde(default)] #[schemars(length(min = 1))] pub endpoint: Option, @@ -661,11 +660,11 @@ pub struct PresidioEntityConfig { #[serde(deny_unknown_fields)] pub struct PresidioConfig { /// Presidio analyzer base URL, e.g. `http://presidio-analyzer:3000`. - /// The data plane appends `/analyze`. + /// The gateway appends `/analyze`. #[schemars(length(min = 1))] pub analyzer_url: String, /// Presidio anonymizer base URL, e.g. `http://presidio-anonymizer:3000`. - /// The data plane appends `/anonymize`. Only called when a detected + /// The gateway appends `/anonymize`. Only called when a detected /// entity's effective action is `mask`. #[schemars(length(min = 1))] pub anonymizer_url: String, diff --git a/crates/aisix-core/src/models/observability_exporter.rs b/crates/aisix-core/src/models/observability_exporter.rs index f0d20ae1..024d764f 100644 --- a/crates/aisix-core/src/models/observability_exporter.rs +++ b/crates/aisix-core/src/models/observability_exporter.rs @@ -93,7 +93,7 @@ pub struct AliyunSlsConfig { #[schemars(length(min = 1))] pub logstore: String, - /// Credential reference resolved by the data plane at delivery time. The plaintext AccessKey is not stored in this resource. + /// Credential reference resolved by the gateway at delivery time. The plaintext AccessKey is not stored in this resource. #[schemars(length(min = 1))] pub credential_ref: String, @@ -135,7 +135,7 @@ pub struct DatadogConfig { ))] pub site: String, - /// Credential reference resolved by the data plane at delivery time. The plaintext Datadog API key is not stored in this resource. + /// Credential reference resolved by the gateway at delivery time. The plaintext Datadog API key is not stored in this resource. #[schemars(length(min = 1))] pub credential_ref: String, @@ -207,11 +207,11 @@ pub struct ObjectStoreConfig { #[serde(default)] pub compression: ObjectStoreCompression, - /// How the data plane authenticates to the bucket. + /// How the gateway authenticates to the bucket. #[serde(default)] pub auth_mode: ObjectStoreAuthMode, - /// Credential reference resolved by the data plane at delivery time. Required when `auth_mode` is `credential_ref`. + /// Credential reference resolved by the gateway at delivery time. Required when `auth_mode` is `credential_ref`. #[serde(default, skip_serializing_if = "String::is_empty")] #[schemars(length(min = 1))] pub credential_ref: String, @@ -240,17 +240,17 @@ pub enum ObjectStoreCompression { None, } -/// How the data plane obtains credentials for the object-storage bucket. +/// How the gateway obtains credentials for the object-storage bucket. #[derive( Debug, Clone, Copy, Default, Serialize, Deserialize, schemars::JsonSchema, PartialEq, Eq, Hash, )] #[serde(rename_all = "snake_case")] pub enum ObjectStoreAuthMode { - /// Resolve `credential_ref` to static keys from data plane environment + /// Resolve `credential_ref` to static keys from gateway environment /// variables named `OBJSTORE_CRED__`. #[default] CredentialRef, - /// Use the data plane host's attached cloud identity. Supported for S3 and GCS only. + /// Use the gateway host's attached cloud identity. Supported for S3 and GCS only. CloudIdentity, } diff --git a/crates/aisix-core/src/models/provider_key.rs b/crates/aisix-core/src/models/provider_key.rs index 84391bd6..ed0c69d4 100644 --- a/crates/aisix-core/src/models/provider_key.rs +++ b/crates/aisix-core/src/models/provider_key.rs @@ -34,7 +34,7 @@ pub struct ProviderKey { #[schemars(length(min = 1))] pub display_name: String, - /// Upstream provider's API key. The data plane receives plaintext so it + /// Upstream provider's API key. The gateway receives plaintext so it /// can authenticate to the upstream provider. Protect the configuration /// store and transport accordingly. // `secret` is the field's former name; stored documents and callers diff --git a/crates/aisix-server/src/export/mod.rs b/crates/aisix-server/src/export/mod.rs index beeefce7..aec567c1 100644 --- a/crates/aisix-server/src/export/mod.rs +++ b/crates/aisix-server/src/export/mod.rs @@ -206,7 +206,7 @@ fn report_secrets(document: &document::ExportDocument, reveal_secrets: bool) { eprintln!( "\n{} secret value(s) were replaced with ${{VAR}} placeholders. Set each variable to the \ - real credential in the data plane's environment before loading this file:", + real credential in the gateway's environment before loading this file:", lines.len() ); for line in lines { diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index c6bf102c..26a919fd 100755 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -7,12 +7,18 @@ # Standalone — operator mounts their own config: # docker run -v ./config.yaml:/etc/aisix/config.yaml ghcr.io/api7/aisix:dev # -# Managed (aisix.cloud tenant) — use the baked-in template + env vars: +# Managed (connected to AISIX Cloud) — use the baked-in template + env vars: # docker run \ # -e AISIX_CONFIG_PATH=/etc/aisix/config.managed.yaml \ -# -e AISIX_MANAGED__REGISTRATION_TOKEN=$DEPLOYMENT_TOKEN \ -# -e AISIX_MANAGED__CP_BASE_URL=https://api.us.aisix.cloud \ +# -e AISIX_MANAGED__CP_BASE_URL \ +# -e AISIX_MANAGED__CP_ETCD_ENDPOINT \ +# -e AISIX_MANAGED__CP_CERT_PEM \ +# -e AISIX_MANAGED__CP_KEY_PEM \ +# -e AISIX_MANAGED__CP_CA_PEM \ +# -v aisix-mtls:/var/lib/aisix \ # ghcr.io/api7/aisix:dev +# The volume preserves the materialized mTLS bundle and gateway identity across +# container restarts. # # The Rust binary's `Config::load_from_path` already layers # `AISIX___` env vars on top of the YAML, so any field diff --git a/schemas/resources/guardrail.schema.json b/schemas/resources/guardrail.schema.json index c372e0ee..5bcd79d5 100644 --- a/schemas/resources/guardrail.schema.json +++ b/schemas/resources/guardrail.schema.json @@ -20,7 +20,7 @@ "type": "string" }, "secret_access_key": { - "description": "Decrypted before projection. Plaintext is held in memory only and is not logged. The data plane passes it to the AWS SDK's static credentials provider.", + "description": "AWS secret access key used to authenticate requests to Amazon Bedrock. The gateway does not log the plaintext value.", "minLength": 1, "type": "string" } @@ -338,7 +338,7 @@ "type": "string" }, "endpoint": { - "description": "Azure Cognitive Services resource endpoint, e.g. `https://my-resource.cognitiveservices.azure.com`. The data plane appends `/contentsafety/text:shieldPrompt?api-version=2024-09-01`.", + "description": "Azure Cognitive Services resource endpoint, e.g. `https://my-resource.cognitiveservices.azure.com`. The gateway appends `/contentsafety/text:shieldPrompt?api-version=2024-09-01`.", "minLength": 1, "type": "string" }, @@ -408,7 +408,7 @@ "type": "array" }, "endpoint": { - "description": "Azure Cognitive Services resource endpoint. The data plane appends `/contentsafety/text:analyze?api-version=2024-09-01`.", + "description": "Azure Cognitive Services resource endpoint. The gateway appends `/contentsafety/text:analyze?api-version=2024-09-01`.", "minLength": 1, "type": "string" }, @@ -562,7 +562,7 @@ "type": "boolean" }, "region": { - "description": "Aliyun region the guardrail lives in, e.g. `cn-shanghai`. The data plane builds the endpoint `https://green-cip..aliyuncs.com`.", + "description": "Aliyun region the guardrail lives in, e.g. `cn-shanghai`. The gateway builds the endpoint `https://green-cip..aliyuncs.com`.", "minLength": 1, "type": "string" }, @@ -660,7 +660,7 @@ "type": "boolean" }, "region": { - "description": "Aliyun region the guardrail lives in, e.g. `cn-shanghai`. The data plane builds the endpoint `https://green-cip..aliyuncs.com`.", + "description": "Aliyun region the guardrail lives in, e.g. `cn-shanghai`. The gateway builds the endpoint `https://green-cip..aliyuncs.com`.", "minLength": 1, "type": "string" }, @@ -769,7 +769,7 @@ }, "endpoint": { "default": null, - "description": "Endpoint override, e.g. a regional or self-hosted Lakera deployment. The data plane appends `/v2/guard`. Defaults to `https://api.lakera.ai`.", + "description": "Endpoint override, e.g. a regional or self-hosted Lakera deployment. The gateway appends `/v2/guard`. Defaults to `https://api.lakera.ai`.", "minLength": 1, "type": "string" }, @@ -878,12 +878,12 @@ "description": "Self-hosted Microsoft Presidio PII detection and anonymization. Analyzer entities can mask or block per entity, and masked entities use the selected anonymize operator. Applies on input, output, or both, including buffered streaming output.", "properties": { "analyzer_url": { - "description": "Presidio analyzer base URL, e.g. `http://presidio-analyzer:3000`. The data plane appends `/analyze`.", + "description": "Presidio analyzer base URL, e.g. `http://presidio-analyzer:3000`. The gateway appends `/analyze`.", "minLength": 1, "type": "string" }, "anonymizer_url": { - "description": "Presidio anonymizer base URL, e.g. `http://presidio-anonymizer:3000`. The data plane appends `/anonymize`. Only called when a detected entity's effective action is `mask`.", + "description": "Presidio anonymizer base URL, e.g. `http://presidio-anonymizer:3000`. The gateway appends `/anonymize`. Only called when a detected entity's effective action is `mask`.", "minLength": 1, "type": "string" }, diff --git a/schemas/resources/observability_exporter.schema.json b/schemas/resources/observability_exporter.schema.json index 2236bd8b..3ec365f7 100644 --- a/schemas/resources/observability_exporter.schema.json +++ b/schemas/resources/observability_exporter.schema.json @@ -2,17 +2,17 @@ "$schema": "http://json-schema.org/draft-07/schema#", "definitions": { "ObjectStoreAuthMode": { - "description": "How the data plane obtains credentials for the object-storage bucket.", + "description": "How the gateway obtains credentials for the object-storage bucket.", "oneOf": [ { - "description": "Resolve `credential_ref` to static keys from data plane environment variables named `OBJSTORE_CRED__`.", + "description": "Resolve `credential_ref` to static keys from gateway environment variables named `OBJSTORE_CRED__`.", "enum": [ "credential_ref" ], "type": "string" }, { - "description": "Use the data plane host's attached cloud identity. Supported for S3 and GCS only.", + "description": "Use the gateway host's attached cloud identity. Supported for S3 and GCS only.", "enum": [ "cloud_identity" ], @@ -156,7 +156,7 @@ "description": "Controls whether logs include prompt and response content. `metadata_only` omits content. `full` includes content truncated by `content_max_bytes`." }, "credential_ref": { - "description": "Credential reference resolved by the data plane at delivery time. The plaintext AccessKey is not stored in this resource.", + "description": "Credential reference resolved by the gateway at delivery time. The plaintext AccessKey is not stored in this resource.", "minLength": 1, "type": "string" }, @@ -242,7 +242,7 @@ } ], "default": "credential_ref", - "description": "How the data plane authenticates to the bucket." + "description": "How the gateway authenticates to the bucket." }, "bucket": { "description": "Bucket for S3 or GCS, or container for Azure Blob, that receives exported files.", @@ -259,7 +259,7 @@ "description": "Compression applied to each NDJSON file before upload." }, "credential_ref": { - "description": "Credential reference resolved by the data plane at delivery time. Required when `auth_mode` is `credential_ref`.", + "description": "Credential reference resolved by the gateway at delivery time. Required when `auth_mode` is `credential_ref`.", "minLength": 1, "type": "string" }, @@ -334,7 +334,7 @@ "description": "Controls whether logs include prompt and response content. `metadata_only` omits content. `full` includes content truncated by `content_max_bytes`." }, "credential_ref": { - "description": "Credential reference resolved by the data plane at delivery time. The plaintext Datadog API key is not stored in this resource.", + "description": "Credential reference resolved by the gateway at delivery time. The plaintext Datadog API key is not stored in this resource.", "minLength": 1, "type": "string" }, diff --git a/schemas/resources/provider_key.schema.json b/schemas/resources/provider_key.schema.json index f2988f35..e44246a2 100644 --- a/schemas/resources/provider_key.schema.json +++ b/schemas/resources/provider_key.schema.json @@ -249,7 +249,7 @@ ] }, "api_key": { - "description": "Upstream provider's API key. The data plane receives plaintext so it can authenticate to the upstream provider. Protect the configuration store and transport accordingly.", + "description": "Upstream provider's API key. The gateway receives plaintext so it can authenticate to the upstream provider. Protect the configuration store and transport accordingly.", "minLength": 1, "type": "string" },