zuplo 7.3.2 → 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.
- package/docs/ai-gateway/apps.mdx +2 -2
- package/docs/ai-gateway/custom-policies.mdx +3 -3
- package/docs/ai-gateway/fallback.mdx +13 -12
- package/docs/ai-gateway/getting-started.mdx +10 -9
- package/docs/ai-gateway/introduction.mdx +19 -18
- package/docs/ai-gateway/managing-apps.mdx +9 -7
- package/docs/ai-gateway/policy-chains.mdx +13 -7
- package/docs/ai-gateway/policy-templates.mdx +4 -3
- package/docs/ai-gateway/usage-limits.mdx +8 -10
- package/docs/api-management/introduction.md +1 -1
- package/docs/articles/api-key-api.mdx +3 -3
- package/docs/articles/custom-ci-cd-azure.mdx +1 -1
- package/docs/articles/custom-ci-cd-bitbucket.mdx +2 -2
- package/docs/articles/custom-code-patterns.md +1 -1
- package/docs/articles/custom-domains.mdx +2 -2
- package/docs/articles/development-options.mdx +4 -4
- package/docs/articles/fastly-zuplo-host-setup.mdx +5 -5
- package/docs/articles/feature-flags.mdx +442 -0
- package/docs/articles/gke-with-upstream-auth-policy.mdx +7 -7
- package/docs/articles/health-checks.mdx +4 -4
- package/docs/articles/hosting-options.mdx +2 -2
- package/docs/articles/local-development-env-variables.mdx +1 -1
- package/docs/articles/metrics-plugins.mdx +1 -1
- package/docs/articles/migration-overview.md +1 -1
- package/docs/articles/monorepo-deployment.mdx +10 -10
- package/docs/articles/performance-testing.mdx +10 -9
- package/docs/articles/plugin-azure-blob.mdx +1 -1
- package/docs/articles/plugin-azure-event-hubs.mdx +2 -2
- package/docs/articles/policies.mdx +2 -2
- package/docs/articles/securing-backend-mtls.mdx +3 -3
- package/docs/articles/securing-the-gateway-with-client-mtls.mdx +3 -3
- package/docs/articles/securing-your-backend.mdx +1 -1
- package/docs/articles/security.mdx +1 -1
- package/docs/articles/terraform.mdx +2 -2
- package/docs/articles/testing.mdx +6 -6
- package/docs/articles/troubleshooting-slow-responses.mdx +5 -6
- package/docs/articles/troubleshooting.md +1 -1
- package/docs/articles/use-openapi-extension-data.mdx +4 -4
- package/docs/articles/waf-ddos-akamai.md +13 -13
- package/docs/articles/waf-ddos-aws-waf-shield.mdx +14 -14
- package/docs/articles/waf-ddos-fastly.mdx +14 -14
- package/docs/articles/waf-ddos.mdx +7 -7
- package/docs/cli/authentication.mdx +1 -1
- package/docs/cli/lint.mdx +103 -0
- package/docs/concepts/how-zuplo-works.mdx +5 -4
- package/docs/concepts/upstream-credentials.mdx +1 -1
- package/docs/dedicated/akamai/architecture.mdx +23 -24
- package/docs/dedicated/akamai/cdn.mdx +20 -20
- package/docs/dedicated/architecture.mdx +28 -27
- package/docs/dedicated/custom-domains.mdx +3 -4
- package/docs/dedicated/federated-gateways.mdx +1 -1
- package/docs/dedicated/networking.mdx +10 -10
- package/docs/dedicated/overview.mdx +3 -3
- package/docs/dedicated/source-control.mdx +6 -5
- package/docs/handlers/custom-handler.mdx +4 -4
- package/docs/handlers/mcp-server.mdx +1 -1
- package/docs/handlers/url-forward.mdx +1 -2
- package/docs/mcp-server/introduction.mdx +4 -4
- package/docs/policies/_index.md +2 -2
- package/docs/policies/ai-gateway-configuration-executor-v2-inbound/schema.json +1 -1
- package/docs/policies/ai-gateway-dlp-inbound/doc.md +79 -45
- package/docs/policies/ai-gateway-dlp-inbound/schema.json +5679 -3359
- package/docs/policies/ai-gateway-metering-v2-inbound/doc.md +13 -13
- package/docs/policies/ai-gateway-metering-v2-inbound/schema.json +1 -1
- package/docs/programmable-api/environment.mdx +1 -1
- package/docs/programmable-api/jwt-service-plugin.mdx +1 -1
- package/docs/programmable-api/logger.mdx +1 -1
- package/docs/programmable-api/runtime-errors.mdx +1 -1
- package/docs/programmable-api/zuplo-context.mdx +3 -3
- package/docs/self-hosted/overview.md +3 -3
- package/package.json +5 -5
|
@@ -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`
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
is
|
|
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
|
-
|
|
33
|
-
|
|
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
|
-
"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"
|
|
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`
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
`
|
|
82
|
-
|
|
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
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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.
|