zuplo 7.4.1 → 7.4.3

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.
Files changed (58) hide show
  1. package/docs/api-management/introduction.md +1 -1
  2. package/docs/articles/api-key-api.mdx +3 -3
  3. package/docs/articles/custom-ci-cd-azure.mdx +1 -1
  4. package/docs/articles/custom-ci-cd-bitbucket.mdx +2 -2
  5. package/docs/articles/custom-code-patterns.md +1 -1
  6. package/docs/articles/custom-domains.mdx +2 -2
  7. package/docs/articles/development-options.mdx +4 -4
  8. package/docs/articles/fastly-zuplo-host-setup.mdx +5 -5
  9. package/docs/articles/feature-flags.mdx +442 -0
  10. package/docs/articles/gke-with-upstream-auth-policy.mdx +7 -7
  11. package/docs/articles/health-checks.mdx +4 -4
  12. package/docs/articles/hosting-options.mdx +2 -2
  13. package/docs/articles/local-development-env-variables.mdx +1 -1
  14. package/docs/articles/metrics-plugins.mdx +1 -1
  15. package/docs/articles/migration-overview.md +1 -1
  16. package/docs/articles/monorepo-deployment.mdx +10 -10
  17. package/docs/articles/performance-testing.mdx +10 -9
  18. package/docs/articles/plugin-azure-blob.mdx +1 -1
  19. package/docs/articles/plugin-azure-event-hubs.mdx +2 -2
  20. package/docs/articles/policies.mdx +2 -2
  21. package/docs/articles/securing-backend-mtls.mdx +3 -3
  22. package/docs/articles/securing-the-gateway-with-client-mtls.mdx +3 -3
  23. package/docs/articles/securing-your-backend.mdx +1 -1
  24. package/docs/articles/security.mdx +1 -1
  25. package/docs/articles/terraform.mdx +2 -2
  26. package/docs/articles/testing.mdx +6 -6
  27. package/docs/articles/troubleshooting-slow-responses.mdx +5 -6
  28. package/docs/articles/troubleshooting.md +1 -1
  29. package/docs/articles/use-openapi-extension-data.mdx +4 -4
  30. package/docs/articles/waf-ddos-akamai.md +13 -13
  31. package/docs/articles/waf-ddos-aws-waf-shield.mdx +14 -14
  32. package/docs/articles/waf-ddos-fastly.mdx +14 -14
  33. package/docs/articles/waf-ddos.mdx +7 -7
  34. package/docs/cli/authentication.mdx +1 -1
  35. package/docs/cli/lint.mdx +103 -0
  36. package/docs/concepts/how-zuplo-works.mdx +5 -4
  37. package/docs/concepts/upstream-credentials.mdx +1 -1
  38. package/docs/dedicated/akamai/architecture.mdx +23 -24
  39. package/docs/dedicated/akamai/cdn.mdx +20 -20
  40. package/docs/dedicated/architecture.mdx +28 -27
  41. package/docs/dedicated/custom-domains.mdx +3 -4
  42. package/docs/dedicated/federated-gateways.mdx +1 -1
  43. package/docs/dedicated/networking.mdx +10 -10
  44. package/docs/dedicated/overview.mdx +3 -3
  45. package/docs/dedicated/source-control.mdx +6 -5
  46. package/docs/handlers/custom-handler.mdx +4 -4
  47. package/docs/handlers/mcp-server.mdx +1 -1
  48. package/docs/handlers/url-forward.mdx +1 -2
  49. package/docs/mcp-server/introduction.mdx +4 -4
  50. package/docs/policies/ai-gateway-dlp-inbound/doc.md +79 -45
  51. package/docs/policies/ai-gateway-dlp-inbound/schema.json +5679 -3359
  52. package/docs/programmable-api/environment.mdx +1 -1
  53. package/docs/programmable-api/jwt-service-plugin.mdx +1 -1
  54. package/docs/programmable-api/logger.mdx +1 -1
  55. package/docs/programmable-api/runtime-errors.mdx +1 -1
  56. package/docs/programmable-api/zuplo-context.mdx +3 -3
  57. package/docs/self-hosted/overview.md +3 -3
  58. package/package.json +5 -5
@@ -3,8 +3,8 @@ title: "Managed Dedicated: Source Control"
3
3
  sidebar_label: "Source Control"
4
4
  ---
5
5
 
6
- Zuplo supports GitOps workflows for managing your API Gateway configuration.
7
- This means that you can store all of your API Gateway configuration in a Git
6
+ Zuplo supports GitOps workflows for managing your Zuplo Gateway configuration.
7
+ This means that you can store all of your Zuplo Gateway configuration in a Git
8
8
  repository and use Git to manage changes to your configuration. This allows you
9
9
  to track changes to your configuration over time, collaborate with others, and
10
10
  easily roll back changes if needed.
@@ -27,7 +27,7 @@ project.
27
27
 
28
28
  ## Create a Git Repository
29
29
 
30
- Next, you will need to create a Git repository to store your API Gateway
30
+ Next, you will need to create a Git repository to store your Zuplo Gateway
31
31
  configuration. You can use a service like GitHub, GitLab, or Bitbucket to create
32
32
  a new repository.
33
33
 
@@ -44,7 +44,8 @@ git push -u origin main
44
44
 
45
45
  If you are using GitHub, you can connect your Zuplo project to your GitHub
46
46
  repository using the Zuplo integration. This will configure Zuplo to
47
- automatically deploy your API Gateway when you push changes to your repository.
47
+ automatically deploy your Zuplo Gateway when you push changes to your
48
+ repository.
48
49
 
49
50
  For the full instructions on how to connect your Zuplo project to GitHub, see
50
51
  [GitHub Integration](../articles/source-control-setup-github.mdx).
@@ -52,7 +53,7 @@ For the full instructions on how to connect your Zuplo project to GitHub, see
52
53
  ## Custom CI: Deploy your API
53
54
 
54
55
  If you aren't using GitHub, or would like to set up a custom CI/CD pipeline, you
55
- can use the Zuplo CLI to deploy your API Gateway.
56
+ can use the Zuplo CLI to deploy your Zuplo Gateway.
56
57
 
57
58
  ```bash
58
59
  npx zuplo deploy --api-key $ZUPLO_API_KEY --project your-project-name --environment my-env
@@ -3,10 +3,10 @@ title: Function Handler (Custom Handler)
3
3
  sidebar_label: Function Handler
4
4
  ---
5
5
 
6
- As an API gateway, the Request Handler is the most important part of a Zuplo
7
- project. This document shows how you can build a custom handler - this is often
8
- used by developers building BFF (backend-for-frontend), doing orchestration or
9
- custom traffic management.
6
+ As a unified gateway for APIs, AI, and MCP, the Request Handler is the most
7
+ important part of a Zuplo project. This document shows how you can build a
8
+ custom handler - this is often used by developers building BFF
9
+ (backend-for-frontend), doing orchestration or custom traffic management.
10
10
 
11
11
  A request handler is a module with an export that fulfills the following type
12
12
  definition (typescript).
@@ -7,7 +7,7 @@ The MCP (Model Context Protocol) Server handler allows you to run a lightweight,
7
7
  stateless MCP server on your gateway that automatically transforms your API
8
8
  routes into MCP tools.
9
9
 
10
- This enables your API gateway to seamlessly serve external AI tools and agents
10
+ This enables your Zuplo Gateway to seamlessly serve external AI tools and agents
11
11
  through [Model Context Protocol](https://modelcontextprotocol.io/introduction)
12
12
  interactions by using your existing APIs, without needing to duplicate
13
13
  functionality or rebuild business logic in your backend.
@@ -5,8 +5,7 @@ sidebar_label: URL Forward
5
5
 
6
6
  The URL Forward handler proxies requests to a different API without writing any
7
7
  code. It appends the incoming path section of the URL onto the specified
8
- `baseUrl` property, making it ideal for creating API gateways and backend
9
- proxying.
8
+ `baseUrl` property, making it ideal for creating gateways and backend proxying.
10
9
 
11
10
  :::tip
12
11
 
@@ -53,9 +53,9 @@ by:
53
53
  4. **Developer Experience**: Easy configuration and deployment using your
54
54
  existing OpenAPI specifications
55
55
 
56
- The MCP Server Handler transforms your existing Zuplo API gateway into a
57
- powerful toolset that AI systems can discover, understand, and invoke - bringing
58
- AI capabilities directly into your business workflows!
56
+ The MCP Server Handler transforms your existing Zuplo Gateway into a powerful
57
+ toolset that AI systems can discover, understand, and invoke - bringing AI
58
+ capabilities directly into your business workflows!
59
59
 
60
60
  ## MCP Implementation Options
61
61
 
@@ -63,7 +63,7 @@ Zuplo provides two approaches for implementing MCP servers:
63
63
 
64
64
  ### 1. MCP Server Handler: Transform Routes into AI Tools
65
65
 
66
- The MCP Server Handler automatically transforms your API gateway routes into MCP
66
+ The MCP Server Handler automatically transforms your gateway routes into MCP
67
67
  tools that AI systems can discover and use.
68
68
 
69
69
  #### How It Works
@@ -8,42 +8,52 @@ Detection runs entirely inside your gateway using the built-in DLP engine (62
8
8
  data types backed by regexes, checksums such as Luhn and IBAN mod-97, and
9
9
  context-word scoring). Nothing is sent to a third-party scanning service.
10
10
 
11
- ## Rules
11
+ ## Rules: inbound and outbound
12
12
 
13
- `rules` is a map. Each key names a built-in data type id (like `id-us-ssn`) or a
14
- group selector (like `pii`, `secret`, or any dash-aligned prefix such as
15
- `secret-aws`); each value is a rule object stating what happens when that type
16
- is found:
13
+ `rules` has exactly two sections `inbound` for what callers send the model
14
+ (system prompt, message text, and tool-call arguments), `outbound` for what the
15
+ model sends back (buffered responses whole, streaming responses as they stream).
16
+ Each direction you include is scanned; each you omit is left untouched. There is
17
+ no "both" shorthand and no mirroring — wanting the same behavior on both sides
18
+ means stating it in both sections.
19
+
20
+ Each section is a map. Keys name a built-in data type id (like `id-us-ssn`), a
21
+ group selector (`pii`, `secret`, or any dash-aligned prefix such as
22
+ `secret-aws`), or one of your custom detectors by name; each value is a rule
23
+ object whose required `action` says what happens on a match:
17
24
 
18
25
  - `mask` — replace the matched text with a placeholder; the conversation
19
26
  continues.
20
27
  - `block` — reject the request (or terminate the response) with an error naming
21
28
  the detected types, never the values.
22
29
  - `log` — record a finding and let the traffic pass; use it to trial a rule.
23
- - `off` — exclude this type from a group enabled by a broader key.
24
-
25
- A rule states its action in one of two ways, never both: a single `action`
26
- applying in both directions, or the directional pair `inboundAction` /
27
- `outboundAction` — `inboundAction` governs what callers send the model,
28
- `outboundAction` governs what the model sends back (buffered responses whole,
29
- streaming responses as they stream). Either directional field alone limits the
30
- rule to that direction.
30
+ - `off` — exclude this type from a group enabled by a broader key in the same
31
+ section.
31
32
 
32
- Types you do not mention are not scanned. The most specific key wins (exact id
33
- beats a prefix beats a group) and the winning entry decides everything for its
34
- type, direction included. When one stretch of text matches multiple rules, the
35
- severest action wins (block > mask > log).
33
+ Because a rule lives inside a direction, everything about it is per-direction
34
+ its action, its detection level, its mask text, its partial masking:
36
35
 
37
36
  ```json
38
37
  "rules": {
39
- "pii": { "inboundAction": "mask", "outboundAction": "block" },
40
- "contact-phone": { "action": "off" },
41
- "secret": { "action": "block" },
42
- "finance-credit-card": { "action": "mask", "partialMask": { "keepLast": 4 } },
43
- "finance-cvv": { "action": "block", "detection": "corroborated" }
38
+ "inbound": {
39
+ "pii": { "action": "mask" },
40
+ "contact-phone": { "action": "off" }
41
+ },
42
+ "outbound": {
43
+ "pii": { "action": "block" },
44
+ "finance-credit-card": { "action": "mask", "partialMask": { "keepLast": 4 } },
45
+ "finance-cvv": { "action": "block", "detection": "corroborated" }
46
+ }
44
47
  }
45
48
  ```
46
49
 
50
+ Within one section: types you do not mention are not scanned; the most specific
51
+ key wins (exact id beats a prefix beats a group) and the winning entry decides
52
+ everything for its type in that direction. When one stretch of text matches
53
+ multiple rules, the severest action wins (block > mask > log). The two sections
54
+ never influence each other, and at least one section must enable at least one
55
+ rule.
56
+
47
57
  ### Detection levels
48
58
 
49
59
  Each type combines its pattern with evidence — a checksum where the format has
@@ -74,29 +84,45 @@ chunks.
74
84
 
75
85
  ## Custom rules
76
86
 
77
- `customRules` adds your own detections: the same rule object plus a `name`, a
78
- regex `pattern`, and optional `context` words (`detection: "corroborated"` then
79
- means "only near one of those words"). Names must be distinct and must not reuse
80
- a built-in type id or group selector built-in types are configured through
81
- `rules`. An invalid pattern or a colliding name fails the configuration at
82
- request time a broken guardrail never degrades into a silent pass-through.
87
+ `customRules` declares your own detectors a `name`, a regex `pattern`, and
88
+ optional `context` words. A detector does nothing by itself: activate it by name
89
+ inside `rules.inbound` or `rules.outbound`, exactly like a built-in type, with
90
+ its own action, detection level, and mask per direction
91
+ (`detection: "corroborated"` then means "only near one of its context words").
92
+ Names must be distinct and must not reuse a built-in type id or group selector.
93
+ A rules key that matches neither a built-in nor a declared detector, an invalid
94
+ pattern, or a colliding name fails the configuration at request time — a broken
95
+ guardrail never degrades into a silent pass-through.
83
96
 
84
97
  ## Streaming responses
85
98
 
86
- Streaming responses are scanned as they stream. Providers emit deltas of a few
87
- characters, so each channel's text is first coalesced into scan pieces of at
88
- least 64 characters (clients concatenate deltas, so only the chunking shifts
89
- never the text). The scanner carries a bounded tail of already-scanned text
90
- (`streaming.maxCarryChars`, default 512) into each new piece's scan, and each
91
- piece is released once the scan including its successor passes so a value
92
- split across pieces is fully maskable before anything is delivered, at the cost
93
- of roughly one coalesced piece (~64 characters) of latency. When a `block` rule
94
- fires mid-stream, the stream terminates with the endpoint's native
95
- content-filter events (OpenAI clients see a `content_filter` error chunk and
96
- `[DONE]`; Anthropic clients see a well-formed `message_delta` with
97
- `stop_reason: "content_filter"` and `message_stop`). Setting
98
- `streaming.boundaryScan: false` scans each chunk alone and releases it
99
- immediately lower cost, but values split across chunks are missed.
99
+ How streaming (SSE) responses are inspected is set by `streaming.mode`:
100
+
101
+ - **`stream` (default)** scan deltas as they flow. Providers emit deltas of a
102
+ few characters, so each channel's text is first coalesced into scan pieces of
103
+ at least 64 characters (clients concatenate deltas, so only the chunking
104
+ shifts never the text). The scanner carries a bounded tail of
105
+ already-scanned text (`streaming.maxCarryChars`, default 512) into each new
106
+ piece's scan, and each piece is released once the scan including its successor
107
+ passes so a value split across pieces is fully maskable before anything is
108
+ delivered, at the cost of roughly one coalesced piece (~64 characters) of
109
+ latency. When a `block` rule fires mid-stream, the stream terminates with the
110
+ endpoint's native content-filter events (OpenAI clients see a `content_filter`
111
+ error chunk and `[DONE]`; Anthropic clients see a well-formed `message_delta`
112
+ with `stop_reason: "content_filter"` and `message_stop`). Setting
113
+ `streaming.boundaryScan: false` scans each chunk alone and releases it
114
+ immediately — lower cost, but values split across chunks are missed.
115
+ - **`buffer`** — collect the entire response first, then scan it exactly like a
116
+ non-streaming response: one pass over each channel's complete text. Detection
117
+ is exact for values of ANY length (no carry window, no chunk boundaries — the
118
+ streaming limits below do not apply), and because nothing has been delivered
119
+ when the verdict lands, a `block` is a clean native 400 error naming the
120
+ detected types instead of a mid-stream termination. The trade is delivery: the
121
+ client receives nothing until the model finishes generating, and the gateway
122
+ holds the whole response in memory. The SSE framing is preserved — clients
123
+ still receive the same events, all at once.
124
+ - **`off`** — streaming responses pass through unscanned, even when rules cover
125
+ the outbound direction. Buffered (non-streaming) responses are still scanned.
100
126
 
101
127
  ## Failure posture
102
128
 
@@ -111,6 +137,10 @@ AI Gateway policies on compatibility dates of 2026-03-01 or later.
111
137
 
112
138
  ## Known limits
113
139
 
140
+ The first four limits apply to `streaming.mode: "stream"` only — `buffer` mode
141
+ scans each channel's complete text in one pass, so chunking cannot hide a value
142
+ from it:
143
+
114
144
  - Masking is complete for streamed values up to two coalesced scan pieces (~128
115
145
  characters) regardless of how finely the provider chunks its deltas, for types
116
146
  whose shape alone is decisive (dashed SSNs, cards, prefixed secrets). A longer
@@ -119,9 +149,13 @@ AI Gateway policies on compatibility dates of 2026-03-01 or later.
119
149
  - A context-gated match (a weak form, or a `corroborated` rule) whose context
120
150
  word arrives only in a LATER piece can leak the characters delivered before
121
151
  the context made it actionable; detection and blocking still fire.
152
+ - Multi-line values such as PEM private key blocks are not detected across
153
+ streaming chunk boundaries.
122
154
  - Streamed `logprobs` are removed from scanned chat streams: masking rewrites
123
- the text they describe, and stale logprobs are worse than absent ones.
155
+ the text they describe, and stale logprobs are worse than absent ones. (This
156
+ also applies to `buffer` mode, which rewrites the same events.)
157
+
158
+ And in every mode:
159
+
124
160
  - Context words must appear in the conversation text itself; JSON field names in
125
161
  your application's data are not visible to the scanner.
126
- - Multi-line values such as PEM private key blocks are not detected across
127
- streaming chunk boundaries.