zuplo 6.72.13 → 6.72.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/articles/migrate-from-apigee.md +1 -1
- package/docs/articles/migrate-from-azure-apim.md +1 -1
- package/docs/articles/migrate-from-kong.md +4 -4
- package/docs/articles/waf-ddos-akamai.md +6 -6
- package/docs/articles/waf-ddos-aws-waf-shield.mdx +6 -6
- package/docs/articles/waf-ddos-fastly.mdx +6 -6
- package/docs/articles/waf-ddos.mdx +1 -1
- package/docs/concepts/authentication.mdx +2 -1
- package/docs/concepts/request-lifecycle.mdx +1 -1
- package/docs/policies/_index.md +1 -13
- package/docs/policies/ai-gateway-model-routing-v2-inbound/doc.md +162 -0
- package/docs/policies/ai-gateway-model-routing-v2-inbound/intro.md +19 -0
- package/docs/policies/ai-gateway-model-routing-v2-inbound/schema.json +263 -0
- package/docs/policies/graphql-cache-inbound/doc.md +1 -1
- package/package.json +4 -4
- package/docs/policies/ab-test-inbound/intro.md +0 -8
- package/docs/policies/ab-test-inbound/policy.ts +0 -14
- package/docs/policies/ab-test-inbound/schema.json +0 -27
- package/docs/policies/ab-test-outbound/intro.md +0 -8
- package/docs/policies/ab-test-outbound/policy.ts +0 -26
- package/docs/policies/ab-test-outbound/schema.json +0 -27
- package/docs/policies/acl-policy-inbound/intro.md +0 -5
- package/docs/policies/acl-policy-inbound/policy.ts +0 -32
- package/docs/policies/acl-policy-inbound/schema.json +0 -52
- package/docs/policies/archive-request-aws-s3-inbound/intro.md +0 -4
- package/docs/policies/archive-request-aws-s3-inbound/policy.ts +0 -58
- package/docs/policies/archive-request-aws-s3-inbound/schema.json +0 -68
- package/docs/policies/archive-request-azure-storage-inbound/doc.md +0 -31
- package/docs/policies/archive-request-azure-storage-inbound/intro.md +0 -4
- package/docs/policies/archive-request-azure-storage-inbound/policy.ts +0 -54
- package/docs/policies/archive-request-azure-storage-inbound/schema.json +0 -53
- package/docs/policies/archive-request-gcp-storage-inbound/doc.md +0 -63
- package/docs/policies/archive-request-gcp-storage-inbound/intro.md +0 -4
- package/docs/policies/archive-request-gcp-storage-inbound/policy.ts +0 -68
- package/docs/policies/archive-request-gcp-storage-inbound/schema.json +0 -47
- package/docs/policies/archive-response-aws-s3-outbound/intro.md +0 -2
- package/docs/policies/archive-response-aws-s3-outbound/policy.ts +0 -59
- package/docs/policies/archive-response-aws-s3-outbound/schema.json +0 -68
- package/docs/policies/archive-response-azure-storage-outbound/doc.md +0 -31
- package/docs/policies/archive-response-azure-storage-outbound/intro.md +0 -3
- package/docs/policies/archive-response-azure-storage-outbound/policy.ts +0 -54
- package/docs/policies/archive-response-azure-storage-outbound/schema.json +0 -53
- package/docs/policies/hmac-auth-inbound/doc.md +0 -30
- package/docs/policies/hmac-auth-inbound/intro.md +0 -10
- package/docs/policies/hmac-auth-inbound/policy.ts +0 -70
- package/docs/policies/hmac-auth-inbound/schema.json +0 -53
- package/docs/policies/ip-restriction-inbound/intro.md +0 -8
- package/docs/policies/ip-restriction-inbound/policy.ts +0 -40
- package/docs/policies/ip-restriction-inbound/schema.json +0 -58
- package/docs/policies/rbac-policy-inbound/intro.md +0 -3
- package/docs/policies/rbac-policy-inbound/policy.ts +0 -42
- package/docs/policies/rbac-policy-inbound/schema.json +0 -52
- package/docs/policies/transform-body-inbound/intro.md +0 -8
- package/docs/policies/transform-body-inbound/policy.ts +0 -16
- package/docs/policies/transform-body-inbound/schema.json +0 -27
- package/docs/policies/transform-body-outbound/intro.md +0 -8
- package/docs/policies/transform-body-outbound/policy.ts +0 -19
- package/docs/policies/transform-body-outbound/schema.json +0 -27
|
@@ -120,7 +120,7 @@ The following table maps common Apigee policies to Zuplo equivalents:
|
|
|
120
120
|
| `ExtractVariables` | [Custom Code Policy](../policies/custom-code-inbound.md) |
|
|
121
121
|
| `XMLToJSON` / `JSONToXML` | [XML to JSON](../policies/xml-to-json-outbound.md) or custom code |
|
|
122
122
|
| `RaiseFault` | Custom code returning an error [Response](../programmable-api/http-problems.md) |
|
|
123
|
-
| `AccessControl` | [
|
|
123
|
+
| `AccessControl` | [Custom Code](../policies/custom-code-inbound.md) |
|
|
124
124
|
| `CORS` | Built-in [CORS configuration](../programmable-api/custom-cors-policy.md) |
|
|
125
125
|
| `JavaScript` callout | [Custom Code Policy](../policies/custom-code-inbound.md) (TypeScript) |
|
|
126
126
|
| `ServiceCallout` | [Custom Code Policy](../policies/custom-code-inbound.md) using `fetch()` |
|
|
@@ -97,7 +97,7 @@ The following table maps common Azure APIM policies to Zuplo equivalents:
|
|
|
97
97
|
| `quota` / `quota-by-key` | [Quota](../policies/quota-inbound.md) |
|
|
98
98
|
| `validate-jwt` | [Open ID JWT Authentication](../policies/open-id-jwt-auth-inbound.md) |
|
|
99
99
|
| `authentication-basic` | [Basic Authentication](../policies/basic-auth-inbound.md) |
|
|
100
|
-
| `ip-filter` | [
|
|
100
|
+
| `ip-filter` | [Custom Code](../policies/custom-code-inbound.md) |
|
|
101
101
|
| `cors` | Built-in [CORS configuration](../programmable-api/custom-cors-policy.md) |
|
|
102
102
|
| `json-to-xml` / `xml-to-json` | [XML to JSON](../policies/xml-to-json-outbound.md) or custom code |
|
|
103
103
|
| `find-and-replace` | [Replace String](../policies/replace-string-outbound.md) |
|
|
@@ -145,13 +145,13 @@ The following table maps common Kong plugins to their Zuplo policy equivalents:
|
|
|
145
145
|
| `basic-auth` | [Basic Authentication](../policies/basic-auth-inbound.md) |
|
|
146
146
|
| `rate-limiting` | [Rate Limiting](../policies/rate-limit-inbound.md) |
|
|
147
147
|
| `rate-limiting-advanced` | [Complex Rate Limiting](../policies/complex-rate-limit-inbound.md) |
|
|
148
|
-
| `request-transformer` | [
|
|
149
|
-
| `response-transformer` | [
|
|
148
|
+
| `request-transformer` | [Custom Code](../policies/custom-code-inbound.md) |
|
|
149
|
+
| `response-transformer` | [Custom Code](../policies/custom-code-outbound.md) |
|
|
150
150
|
| `cors` | Built-in [CORS configuration](../programmable-api/custom-cors-policy.md) |
|
|
151
|
-
| `ip-restriction` | [
|
|
151
|
+
| `ip-restriction` | [Custom Code](../policies/custom-code-inbound.md) |
|
|
152
152
|
| `request-size-limiting` | [Request Size Limit](../policies/request-size-limit-inbound.md) |
|
|
153
153
|
| `request-validation` | [Request Validation](../policies/request-validation-inbound.md) |
|
|
154
|
-
| `acl` | [
|
|
154
|
+
| `acl` | [Custom Code](../policies/custom-code-inbound.md) |
|
|
155
155
|
| Custom Lua plugin | [Custom Code Policy](../policies/custom-code-inbound.md) (TypeScript) |
|
|
156
156
|
|
|
157
157
|
### Step 3: Translate plugin configuration
|
|
@@ -24,20 +24,20 @@ your API Gateway. This is a good way to ensure that only Akamai can access your
|
|
|
24
24
|
API Gateway. However, as Akamai is a multi-tenant service, this method isn't
|
|
25
25
|
sufficient to protect unauthorized traffic from hitting your API Gateway.
|
|
26
26
|
|
|
27
|
-
In Zuplo, you can use
|
|
28
|
-
[
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
In Zuplo, you can use a
|
|
28
|
+
[custom code policy](../policies/custom-code-inbound.mdx) to limit traffic to
|
|
29
|
+
only the Akamai IP addresses. Add a module in your project (for example,
|
|
30
|
+
`modules/ip-restriction.ts`) that allows only your permitted IP ranges, then
|
|
31
31
|
configure the policy with the IP ranges that Akamai publishes for your account
|
|
32
32
|
in Akamai Control Center.
|
|
33
33
|
|
|
34
34
|
```json
|
|
35
35
|
{
|
|
36
36
|
"name": "allow-akamai-only",
|
|
37
|
-
"policyType": "
|
|
37
|
+
"policyType": "custom-code-inbound",
|
|
38
38
|
"handler": {
|
|
39
39
|
"export": "default",
|
|
40
|
-
"module": "$import(./modules/ip-restriction
|
|
40
|
+
"module": "$import(./modules/ip-restriction)",
|
|
41
41
|
"options": {
|
|
42
42
|
"allowedIpAddresses": ["23.32.0.0/11", "104.64.0.0/10"]
|
|
43
43
|
}
|
|
@@ -26,20 +26,20 @@ way to ensure that only CloudFront can access your API Gateway. However, as
|
|
|
26
26
|
CloudFront is available to any AWS customer, this method isn't sufficient to
|
|
27
27
|
protect unauthorized traffic from hitting your API Gateway.
|
|
28
28
|
|
|
29
|
-
In Zuplo, you can use
|
|
30
|
-
[
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
In Zuplo, you can use a
|
|
30
|
+
[custom code policy](../policies/custom-code-inbound.mdx) to limit traffic to
|
|
31
|
+
only the CloudFront IP addresses. Add a module in your project (for example,
|
|
32
|
+
`modules/ip-restriction.ts`) that allows only your permitted IP ranges, then
|
|
33
33
|
configure the policy with the `CLOUDFRONT` ranges from the
|
|
34
34
|
[AWS IP address ranges list](https://ip-ranges.amazonaws.com/ip-ranges.json).
|
|
35
35
|
|
|
36
36
|
```json
|
|
37
37
|
{
|
|
38
38
|
"name": "allow-cloudfront-only",
|
|
39
|
-
"policyType": "
|
|
39
|
+
"policyType": "custom-code-inbound",
|
|
40
40
|
"handler": {
|
|
41
41
|
"export": "default",
|
|
42
|
-
"module": "$import(./modules/ip-restriction
|
|
42
|
+
"module": "$import(./modules/ip-restriction)",
|
|
43
43
|
"options": {
|
|
44
44
|
"allowedIpAddresses": ["13.32.0.0/15", "13.35.0.0/16"]
|
|
45
45
|
}
|
|
@@ -27,20 +27,20 @@ your API Gateway. This is a good way to ensure that only Fastly can access your
|
|
|
27
27
|
API Gateway. However, as Fastly is a multi-tenant service, this method isn't
|
|
28
28
|
sufficient to protect unauthorized traffic from hitting your API Gateway.
|
|
29
29
|
|
|
30
|
-
In Zuplo, you can use
|
|
31
|
-
[
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
In Zuplo, you can use a
|
|
31
|
+
[custom code policy](../policies/custom-code-inbound.mdx) to limit traffic to
|
|
32
|
+
only the Fastly IP addresses. Add a module in your project (for example,
|
|
33
|
+
`modules/ip-restriction.ts`) that allows only your permitted IP ranges, then
|
|
34
34
|
configure the policy with the address ranges from
|
|
35
35
|
[Fastly's public IP list](https://api.fastly.com/public-ip-list).
|
|
36
36
|
|
|
37
37
|
```json
|
|
38
38
|
{
|
|
39
39
|
"name": "allow-fastly-only",
|
|
40
|
-
"policyType": "
|
|
40
|
+
"policyType": "custom-code-inbound",
|
|
41
41
|
"handler": {
|
|
42
42
|
"export": "default",
|
|
43
|
-
"module": "$import(./modules/ip-restriction
|
|
43
|
+
"module": "$import(./modules/ip-restriction)",
|
|
44
44
|
"options": {
|
|
45
45
|
"allowedIpAddresses": ["151.101.0.0/16", "199.232.0.0/16"]
|
|
46
46
|
}
|
|
@@ -31,7 +31,7 @@ Many common WAF functions can be implemented directly in Zuplo using policies,
|
|
|
31
31
|
without the need for a separate WAF service:
|
|
32
32
|
|
|
33
33
|
- **IP Restriction** - Block or allow requests from specific IP addresses using
|
|
34
|
-
|
|
34
|
+
a [custom code policy](../policies/custom-code-inbound.mdx)
|
|
35
35
|
- **Geolocation Blocking** - Route or block requests based on country using
|
|
36
36
|
[custom policies](../guides/geolocation-backend-routing.mdx)
|
|
37
37
|
- **Rate Limiting** - Protect against abuse with built-in
|
|
@@ -79,7 +79,8 @@ users already authenticate with an identity provider.
|
|
|
79
79
|
- [mTLS](../articles/securing-the-gateway-with-client-mtls.mdx) - Mutual TLS
|
|
80
80
|
certificate authentication
|
|
81
81
|
- [LDAP](../policies/ldap-auth-inbound.mdx) - LDAP directory authentication
|
|
82
|
-
- [HMAC](../policies/
|
|
82
|
+
- [HMAC](../policies/custom-code-inbound.mdx) - Hash-based message
|
|
83
|
+
authentication via a custom code policy
|
|
83
84
|
|
|
84
85
|
## Combining authentication methods
|
|
85
86
|
|
|
@@ -50,7 +50,7 @@ security headers, [logging](../articles/logging.mdx), analytics.
|
|
|
50
50
|
| Validate request bodies | [Inbound policy](../policies/request-validation-inbound.mdx) |
|
|
51
51
|
| Forward to a backend | [URL Forward Handler](../handlers/url-forward.mdx) |
|
|
52
52
|
| Return custom responses | [Function Handler](../handlers/custom-handler.mdx) |
|
|
53
|
-
| Transform response bodies | [
|
|
53
|
+
| Transform response bodies | [Custom code policy](../policies/custom-code-outbound.mdx) |
|
|
54
54
|
| Add headers to all responses | [Response hook](../programmable-api/hooks.mdx) |
|
|
55
55
|
| Log every request | [Response final hook](../programmable-api/hooks.mdx) |
|
|
56
56
|
| Normalize URLs before routing | [Pre-routing hook](../programmable-api/runtime-extensions.mdx) |
|
package/docs/policies/_index.md
CHANGED
|
@@ -2,21 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
| Policy ID | Name | Description | Products |
|
|
4
4
|
| --- | --- | --- | --- |
|
|
5
|
-
| ab-test-inbound | A/B Test Inbound | An A/B test policy is used to handle requests differently based on parameters such as user, ip, etc. | api-gateway |
|
|
6
|
-
| ab-test-outbound | A/B Test Outbound | An A/B test policy is used to handle responses differently based on parameters such as user, ip, etc. | api-gateway |
|
|
7
|
-
| acl-policy-inbound | Access Control List | The access control list inbound policy limits access to resources based on parameters on the authenticated user. | api-gateway |
|
|
8
5
|
| set-query-params-inbound | Add or Set Query Parameters | Adds or sets query parameters on the incoming request. | api-gateway |
|
|
9
6
|
| set-headers-inbound | Add or Set Request Headers | Adds or sets headers on the incoming request. | api-gateway |
|
|
7
|
+
| ai-gateway-model-routing-v2-inbound | AI Gateway Model Routing (v2) | Matches AI Gateway requests against curated allow lists or open block lists, then stores the winning `AIGatewayRouteTarget` for the route handler. | ai-gateway |
|
|
10
8
|
| akamai-ai-firewall | Akamai AI Firewall | Akamai AI Firewall Inbound Policy | ai-gateway |
|
|
11
9
|
| akamai-firewall-for-ai-outbound | Akamai Firewall for AI | Inspects each upstream response with Akamai's Firewall for AI detect API and replaces the response with a `403 Forbidden` if Akamai returns a `deny` rule. Useful behind AI-powered APIs to filter unsafe completions, sensitive data exposure, and toxic content before they reach the client. The body, headers, URL, and query string sent to Akamai are configurable; by default only the response body is captured. Bodies are read from a clone so the client still receives the original. | api-gateway |
|
|
12
10
|
| akamai-firewall-for-ai-inbound | Akamai Firewall for AI | Inspects each incoming request with Akamai's Firewall for AI detect API and blocks the request if Akamai returns a `deny` rule. Useful in front of AI-powered APIs to filter prompt injection, jailbreaks, and other unsafe inputs before they reach the model. The body, headers, URL, and query string sent to Akamai are configurable; by default only the request body is captured. Bodies are read from a clone so the upstream handler still sees the original. | api-gateway |
|
|
13
11
|
| amberflo-metering-inbound | Amberflo Metering / Billing | Amberflo is a usage metering and billing service. This policy allows you to send metering calls for each API to their meter ingest endpoint. | api-gateway |
|
|
14
12
|
| api-key-inbound | API Key Authentication | Authenticates requests based on API Keys using Zuplo's built-in API key management. This policy validates API keys against Zuplo's key storage, caches results for performance, and automatically adds user information to authenticated requests. | api-gateway |
|
|
15
|
-
| archive-request-aws-s3-inbound | Archive Request to AWS S3 | Archive the incoming request body to AWS S3 storage | api-gateway |
|
|
16
|
-
| archive-request-azure-storage-inbound | Archive Request to Azure Storage | Archive the incoming request to Azure blob storage. | api-gateway |
|
|
17
|
-
| archive-request-gcp-storage-inbound | Archive Request to GCP Storage | Archive the incoming request to Google Cloud Storage. | api-gateway |
|
|
18
|
-
| archive-response-aws-s3-outbound | Archive Response to AWS S3 | Archive the outgoing response body to AWS S3 storage | api-gateway |
|
|
19
|
-
| archive-response-azure-storage-outbound | Archive Response to Azure Storage | Archive the outgoing response to Azure blob storage. | api-gateway |
|
|
20
13
|
| audit-log-inbound | Audit Logs | Capture detailed logs of requests for auditing purposes. The policy emits one structured CloudEvent per request, and user code can emit additional events via the static `log()` method. | api-gateway |
|
|
21
14
|
| auth0-jwt-auth-inbound | Auth0 JWT Auth | Authenticate users using Auth0 issued JWT tokens. | api-gateway |
|
|
22
15
|
| authzen-inbound | AuthZEN Authorization | Authorize requests using an AuthZEN compatible PDP | api-gateway |
|
|
@@ -48,9 +41,7 @@
|
|
|
48
41
|
| graphql-complexity-limit-inbound | GraphQL Complexity Limit | Policy that limits the complexity and depth of GraphQL queries to prevent abuse. Protects your GraphQL API from expensive queries that could cause performance issues or denial of service attacks. | api-gateway |
|
|
49
42
|
| graphql-disable-introspection-inbound | GraphQL Disable Introspection | Policy that disables GraphQL introspection queries in production. Introspection allows clients to discover the schema, which can be a security risk as it exposes your entire API structure. | api-gateway |
|
|
50
43
|
| graphql-introspection-filter-outbound | GraphQL Introspection Filter | Filters GraphQL introspection responses to exclude specific types and fields. This policy intercepts GraphQL introspection query responses and removes configured types and fields from the schema. Useful for hiding internal types or sensitive fields from the public schema. | api-gateway |
|
|
51
|
-
| hmac-auth-inbound | HMAC Auth | Authenticate requests using the HMAC-SHA256 authentication scheme. | api-gateway |
|
|
52
44
|
| http-deprecation-outbound | HTTP Deprecation | Sets HTTP deprecation headers on the outgoing response following the IETF HTTP Deprecation Header standard. Supports the Deprecation, Sunset, and Link headers. | api-gateway |
|
|
53
|
-
| ip-restriction-inbound | IP Restriction | Block or allow requests based on their IP address. | api-gateway |
|
|
54
45
|
| validate-json-schema-inbound | JSON Body Validation (deprecated) | Validates the body of an incoming request based on a JSON schema. | api-gateway |
|
|
55
46
|
| open-id-jwt-auth-inbound | JWT Auth | The Open ID JWT Authentication policy allows you to authenticate incoming requests using an Open ID compliant bearer token. | api-gateway |
|
|
56
47
|
| jwt-scopes-inbound | JWT Scope Validation | Validates that the JWT token includes specific scopes | api-gateway |
|
|
@@ -82,7 +73,6 @@
|
|
|
82
73
|
| query-param-to-header-inbound | Query Parameter to Header | Extracts a query parameter and sets it as a header in the request. | api-gateway |
|
|
83
74
|
| quota-inbound | Quota | The Quota policy enables you to set monthly, weekly, daily or hourly quotas on your API. | api-gateway |
|
|
84
75
|
| rate-limit-inbound | Rate Limiting | Rate limiting policy to control the number of requests to your API. Supports multiple identification strategies (by user, IP, header, etc.) and can operate in strict or async mode for different performance characteristics. | api-gateway |
|
|
85
|
-
| rbac-policy-inbound | RBAC Authorization | The RBAC authorization inbound policy limits access to resources based on the roles of the authenticated user. | api-gateway |
|
|
86
76
|
| readme-metrics-inbound | Readme Metrics | Readme is a developer documentation and API metrics company. This policy pushes logs to their API calls dashboard. | api-gateway |
|
|
87
77
|
| remove-query-params-inbound | Remove Query Parameters | Remove query parameters from the incoming request | api-gateway |
|
|
88
78
|
| remove-headers-inbound | Remove Request Headers | Remove headers from the incoming request. | api-gateway |
|
|
@@ -102,8 +92,6 @@
|
|
|
102
92
|
| stripe-webhook-verification-inbound | Stripe Webhook Auth | The Stripe Webhook policy validates the authenticity of an incoming Stripe webhook. | api-gateway |
|
|
103
93
|
| supabase-jwt-auth-inbound | Supabase JWT Auth | The Supabase JWT Authentication policy supports user JWT tokens created by Supabase. | api-gateway |
|
|
104
94
|
| traffic-splitting-inbound | Traffic Splitting | Splits traffic randomly across a set of weighted base paths. On each request one base path is selected (weighted by `weight`) and written to the request custom context at `customOutputProperty`. Reference it from a later URL Rewrite `rewritePattern` or URL Forward `baseUrl`, e.g. `${context.custom.trafficSplitting.basePath}`. | api-gateway |
|
|
105
|
-
| transform-body-inbound | Transform Request Body | Transform the body of an incoming request. | api-gateway |
|
|
106
|
-
| transform-body-outbound | Transform Response Body | Transform the body of an outgoing response. | api-gateway |
|
|
107
95
|
| upstream-aws-federated-auth-inbound | Upstream AWS Federated Auth | Resolves AWS credentials with STS AssumeRoleWithWebIdentity using Zuplo's ambient OIDC identity — no AWS keys are stored anywhere. The role's trust policy must trust the Zuplo OIDC identity provider. Resolved credentials are registered on the request context for the AWS Lambda handler and custom code to sign upstream requests with `AwsClient.fromContext`. This policy does not itself sign or forward the request. | api-gateway |
|
|
108
96
|
| upstream-aws-service-auth-inbound | Upstream AWS Service Auth | Resolves AWS credentials from static access keys (optionally exchanged for an IAM role's temporary credentials via STS AssumeRole) and registers them on the request context. The AWS Lambda handler and custom code read them with `AwsClient.fromContext` to sign upstream requests. This policy does not itself sign or forward the request. | api-gateway |
|
|
109
97
|
| upstream-azure-ad-service-auth-inbound | Upstream Azure AD Service Auth | Uses Azure Active Directory to add an Authorization header to the request in order to authenticate requests using Azure identity. | api-gateway |
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# AI Gateway Model Routing (v2) Policy
|
|
2
|
+
|
|
3
|
+
The AI Gateway Model Routing (v2) policy applies declarative allow or block
|
|
4
|
+
rules to AI requests. Configured targets use `provider/model` form and split on
|
|
5
|
+
the first slash, so provider-specific model IDs can contain additional slashes.
|
|
6
|
+
|
|
7
|
+
## Configuration
|
|
8
|
+
|
|
9
|
+
Set a non-empty `models` object containing `completions`, `embeddings`, or both.
|
|
10
|
+
Each capability uses exactly one mode:
|
|
11
|
+
|
|
12
|
+
- `allowList` is curated mode. Only listed `main` models are accepted, entry 0
|
|
13
|
+
is the default when the request omits `model`, and entries can include
|
|
14
|
+
`backup`, `fallbackTimeoutSeconds`, and `quotaFallback`.
|
|
15
|
+
- `blockList` is open-but-filtered mode. Any unblocked target can be requested,
|
|
16
|
+
but every request must include `model`; this mode has no defaults or
|
|
17
|
+
fallbacks.
|
|
18
|
+
|
|
19
|
+
Because Responses management operations such as `GET /v1/responses/{id}` and
|
|
20
|
+
`DELETE /v1/responses/{id}` have no request body, attach curated `allowList`
|
|
21
|
+
rules (or a custom routing policy that supplies an OpenAI selection) to those
|
|
22
|
+
operations. A `blockList` policy cannot select credentials for a bodyless
|
|
23
|
+
request because that mode intentionally has no default.
|
|
24
|
+
|
|
25
|
+
An allow-list entry can be a string shorthand or a full target object:
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{
|
|
29
|
+
"name": "ai-gateway-model-routing-v2-inbound",
|
|
30
|
+
"policyType": "ai-gateway-model-routing-v2",
|
|
31
|
+
"handler": {
|
|
32
|
+
"export": "AIGatewayModelRoutingV2InboundPolicy",
|
|
33
|
+
"module": "$import(@zuplo/runtime)",
|
|
34
|
+
"options": {
|
|
35
|
+
"models": {
|
|
36
|
+
"completions": {
|
|
37
|
+
"allowList": [
|
|
38
|
+
"openai/gpt-5",
|
|
39
|
+
{
|
|
40
|
+
"main": "anthropic/claude-sonnet-4-6",
|
|
41
|
+
"backup": "openai/gpt-5-mini",
|
|
42
|
+
"fallbackTimeoutSeconds": 30,
|
|
43
|
+
"quotaFallback": "anthropic/claude-haiku-4-5"
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
"embeddings": {
|
|
48
|
+
"blockList": ["openai/legacy-embedding-model"]
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The first slash separates the provider from the model. Model IDs may contain
|
|
57
|
+
additional slashes, such as `my-fireworks/accounts/fireworks/models/llama-v3`.
|
|
58
|
+
Provider and model matching is case-insensitive. In curated mode the configured
|
|
59
|
+
casing is preserved when the request is sent upstream.
|
|
60
|
+
|
|
61
|
+
## Request behavior
|
|
62
|
+
|
|
63
|
+
Clients can send a bare model name or `provider/model`. In curated mode, a bare
|
|
64
|
+
name selects the one allow-list `main` with that model name; an ambiguous name
|
|
65
|
+
receives a 400 response asking for `provider/model`. In block-list mode, bare
|
|
66
|
+
Chat Completions and Embeddings models use OpenAI, while native Messages and
|
|
67
|
+
Responses models use Anthropic and OpenAI respectively.
|
|
68
|
+
|
|
69
|
+
`/v1/embeddings` uses the `embeddings` rules; Chat Completions, Responses, and
|
|
70
|
+
Anthropic Messages use `completions` rules. A request containing `/` is treated
|
|
71
|
+
as `provider/model`, so model IDs containing slashes must include their
|
|
72
|
+
provider.
|
|
73
|
+
|
|
74
|
+
The pass-through routes are provider-native: `/v1/messages` accepts Anthropic
|
|
75
|
+
targets and `/v1/responses` accepts OpenAI targets. A request that explicitly
|
|
76
|
+
selects the wrong provider receives a 400 response. An incompatible entry-0
|
|
77
|
+
default is a policy configuration error.
|
|
78
|
+
|
|
79
|
+
## Fallback behavior
|
|
80
|
+
|
|
81
|
+
When `backup` is configured, the gateway fails over after a retryable error or
|
|
82
|
+
after `fallbackTimeoutSeconds` (60 seconds by default). The timeout must be from
|
|
83
|
+
1 through 300 seconds. `quotaFallback` independently selects another model after
|
|
84
|
+
a usage-limit-exceeded signal. Fallbacks do not chain through another allow-list
|
|
85
|
+
entry.
|
|
86
|
+
|
|
87
|
+
Retry and timeout backups apply to translated Chat Completions and Embeddings
|
|
88
|
+
requests. Native `/v1/messages` and `/v1/responses` requests are passed through
|
|
89
|
+
without retrying a `backup`; `AIGatewayModelRouting.set` still validates every
|
|
90
|
+
configured target and credential eagerly. A same-native-provider `quotaFallback`
|
|
91
|
+
can still serve those routes after a usage-limit-exceeded signal.
|
|
92
|
+
|
|
93
|
+
## Write your own routing policy
|
|
94
|
+
|
|
95
|
+
Everything this policy does is built on two public primitives, so a custom
|
|
96
|
+
inbound policy can replace it entirely. The policy's job is to collapse its
|
|
97
|
+
allow list to one winning target and store it; custom code makes the same call
|
|
98
|
+
with whatever logic it wants:
|
|
99
|
+
|
|
100
|
+
- `AIGatewayModels.load(context)` returns the cached provider catalog, including
|
|
101
|
+
each model's capability, status, and per-token pricing.
|
|
102
|
+
- `AIGatewayModelRouting.set(context, routing)` validates the routing, resolves
|
|
103
|
+
provider credentials internally, and stores the selection that the AI Gateway
|
|
104
|
+
handler consumes.
|
|
105
|
+
|
|
106
|
+
A per-capability target is the same `AIGatewayRouteTarget` shape used by
|
|
107
|
+
`allowList` entries: a `"provider/model"` string, or an object with `main` and
|
|
108
|
+
optional `backup`, `fallbackTimeoutSeconds`, and `quotaFallback`.
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
import {
|
|
112
|
+
AIGatewayModelRouting,
|
|
113
|
+
AIGatewayModels,
|
|
114
|
+
type ZuploContext,
|
|
115
|
+
type ZuploRequest,
|
|
116
|
+
} from "@zuplo/runtime";
|
|
117
|
+
|
|
118
|
+
export default async function routeModel(
|
|
119
|
+
request: ZuploRequest,
|
|
120
|
+
context: ZuploContext
|
|
121
|
+
) {
|
|
122
|
+
const providers = await AIGatewayModels.load(context);
|
|
123
|
+
const openAI = providers.find((provider) => provider.name === "openai");
|
|
124
|
+
const model = openAI?.models.find(
|
|
125
|
+
(candidate) =>
|
|
126
|
+
candidate.capability === "completions" && candidate.status === "active"
|
|
127
|
+
);
|
|
128
|
+
if (!model) {
|
|
129
|
+
throw new Error("No active OpenAI completions model is available");
|
|
130
|
+
}
|
|
131
|
+
await AIGatewayModelRouting.set(context, {
|
|
132
|
+
completions: {
|
|
133
|
+
main: `openai/${model.model}`,
|
|
134
|
+
backup: "anthropic/claude-sonnet-4-6",
|
|
135
|
+
fallbackTimeoutSeconds: 30,
|
|
136
|
+
},
|
|
137
|
+
});
|
|
138
|
+
return request;
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Attach the module as an ordinary inbound policy on the AI Gateway route instead
|
|
143
|
+
of (or before) the built-in model-routing policy:
|
|
144
|
+
|
|
145
|
+
```json
|
|
146
|
+
{
|
|
147
|
+
"name": "my-model-routing-inbound",
|
|
148
|
+
"policyType": "custom-code-inbound",
|
|
149
|
+
"handler": {
|
|
150
|
+
"export": "default",
|
|
151
|
+
"module": "$import(./modules/my-model-routing)"
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
`AIGatewayModelRouting.get(context)` returns the sanitized, normalized routing
|
|
157
|
+
set for the current request; it never returns credentials. The AI Gateway
|
|
158
|
+
handler consumes this selection even when the built-in model-routing policy is
|
|
159
|
+
not attached to the route. Prefer one routing policy per route. If you compose
|
|
160
|
+
policies intentionally, a custom policy before the built-in policy wins because
|
|
161
|
+
the built-in policy preserves an existing selection. A custom policy after it
|
|
162
|
+
can replace an allowed selection, while a built-in rejection stops the chain.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
The AI Gateway Model Routing (v2) policy selects models with either a curated
|
|
2
|
+
`allowList` or an open-but-filtered `blockList`. Allow-list entries accept the
|
|
3
|
+
string shorthand `"provider/model"` or an object with `main`, `backup`,
|
|
4
|
+
`fallbackTimeoutSeconds`, and `quotaFallback`; entry zero is the default when a
|
|
5
|
+
curated request omits `model`, while block-list mode requires every request to
|
|
6
|
+
name a model.
|
|
7
|
+
|
|
8
|
+
Request model references split on the first slash, match provider and model
|
|
9
|
+
case-insensitively, and preserve configured casing upstream. Clients may send a
|
|
10
|
+
bare model name: curated rules resolve a unique allow-list match, while open
|
|
11
|
+
rules default to OpenAI except on Anthropic-native Messages routes. Bodyless
|
|
12
|
+
Responses management operations need curated or custom routing because
|
|
13
|
+
block-list mode has no default. Retry backups apply to translated Chat
|
|
14
|
+
Completions and Embeddings, not native pass-through routes; quota fallbacks
|
|
15
|
+
remain independent and fallbacks do not chain.
|
|
16
|
+
|
|
17
|
+
Custom inbound policies can inspect `AIGatewayModels.load(context)` and call
|
|
18
|
+
`AIGatewayModelRouting.set(context, routing)` to select the same target without
|
|
19
|
+
attaching the built-in policy. This policy is in beta.
|