zuplo 6.70.69 → 6.70.71

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 (93) hide show
  1. package/docs/ai-gateway/getting-started.mdx +14 -9
  2. package/docs/ai-gateway/integrations/ai-sdk.mdx +17 -0
  3. package/docs/ai-gateway/introduction.mdx +12 -10
  4. package/docs/ai-gateway/providers.mdx +2 -0
  5. package/docs/analytics/access-and-entitlements.md +71 -0
  6. package/docs/analytics/overview.md +63 -0
  7. package/docs/analytics/reference/metrics-glossary.md +105 -0
  8. package/docs/analytics/reference/url-parameters.md +66 -0
  9. package/docs/analytics/shared-controls.md +121 -0
  10. package/docs/analytics/tabs/agents.md +88 -0
  11. package/docs/analytics/tabs/consumers.md +73 -0
  12. package/docs/analytics/tabs/graphql.md +77 -0
  13. package/docs/analytics/tabs/mcp.md +80 -0
  14. package/docs/analytics/tabs/origins.md +82 -0
  15. package/docs/analytics/tabs/requests.md +96 -0
  16. package/docs/articles/api-key-buckets.mdx +4 -2
  17. package/docs/articles/archiving-requests-to-storage.mdx +4 -4
  18. package/docs/articles/branch-based-deployments.mdx +10 -8
  19. package/docs/articles/ci-cd-github/basic-deployment.mdx +10 -1
  20. package/docs/articles/ci-cd-github/cleanup-on-branch-delete.mdx +52 -31
  21. package/docs/articles/ci-cd-github/deploy-and-test.mdx +14 -1
  22. package/docs/articles/ci-cd-github/local-testing.mdx +3 -1
  23. package/docs/articles/ci-cd-github/pr-preview-environments.mdx +53 -10
  24. package/docs/articles/custom-ci-cd-azure.mdx +1 -1
  25. package/docs/articles/custom-ci-cd-bitbucket.mdx +1 -1
  26. package/docs/articles/custom-ci-cd-circleci.mdx +1 -1
  27. package/docs/articles/custom-ci-cd-github.mdx +12 -3
  28. package/docs/articles/custom-ci-cd-gitlab.mdx +1 -1
  29. package/docs/articles/graphql.mdx +276 -0
  30. package/docs/articles/monetization/api-access.mdx +184 -0
  31. package/docs/articles/monetization/meters.mdx +4 -4
  32. package/docs/articles/monetization/monetization-policy.md +4 -1
  33. package/docs/articles/monetization/private-plans.md +3 -4
  34. package/docs/articles/monetization/stripe-integration.md +9 -0
  35. package/docs/articles/monetization/subscription-lifecycle.md +12 -11
  36. package/docs/articles/monorepo-deployment.mdx +37 -5
  37. package/docs/articles/opentelemetry.mdx +5 -2
  38. package/docs/articles/securing-the-gateway-with-client-mtls.mdx +68 -43
  39. package/docs/articles/step-1-setup-basic-gateway.mdx +1 -3
  40. package/docs/articles/step-2-add-rate-limiting.mdx +1 -1
  41. package/docs/articles/testing.mdx +1 -1
  42. package/docs/articles/troubleshooting.md +7 -3
  43. package/docs/articles/waf-ddos-akamai.md +35 -16
  44. package/docs/articles/waf-ddos-aws-waf-shield.mdx +35 -16
  45. package/docs/articles/waf-ddos-fastly.mdx +10 -7
  46. package/docs/cli/deploy.mdx +44 -9
  47. package/docs/cli/deploy.partial.mdx +44 -9
  48. package/docs/concepts/api-keys.md +2 -2
  49. package/docs/dev-portal/zudoku/components/callout.mdx +11 -18
  50. package/docs/dev-portal/zudoku/components/sidecar-box.mdx +131 -0
  51. package/docs/dev-portal/zudoku/configuration/api-catalog.md +62 -42
  52. package/docs/dev-portal/zudoku/configuration/api-reference.md +5 -4
  53. package/docs/dev-portal/zudoku/configuration/navigation.mdx +70 -7
  54. package/docs/dev-portal/zudoku/configuration/search.md +36 -0
  55. package/docs/dev-portal/zudoku/configuration/site.md +38 -0
  56. package/docs/dev-portal/zudoku/customization/colors-theme.mdx +51 -40
  57. package/docs/errors/rate-limit-exceeded.mdx +30 -3
  58. package/docs/guides/canary-routing-for-employees.mdx +103 -39
  59. package/docs/guides/modify-openapi-paths.mdx +3 -3
  60. package/docs/handlers/legacy-dev-portal-handler.mdx +1 -1
  61. package/docs/handlers/mcp-server.mdx +13 -11
  62. package/docs/handlers/url-forward.mdx +5 -1
  63. package/docs/handlers/url-rewrite.mdx +7 -2
  64. package/docs/handlers/websocket-handler.mdx +5 -1
  65. package/docs/mcp-gateway/observability/logging.mdx +19 -12
  66. package/docs/mcp-server/resources.mdx +27 -15
  67. package/docs/mcp-server/testing.mdx +0 -2
  68. package/docs/policies/_index.md +2 -0
  69. package/docs/policies/archive-request-azure-storage-inbound/doc.md +1 -1
  70. package/docs/policies/archive-response-azure-storage-outbound/doc.md +1 -1
  71. package/docs/policies/data-loss-prevention-inbound/doc.md +116 -0
  72. package/docs/policies/data-loss-prevention-inbound/intro.md +15 -0
  73. package/docs/policies/data-loss-prevention-inbound/schema.json +220 -0
  74. package/docs/policies/data-loss-prevention-outbound/doc.md +116 -0
  75. package/docs/policies/data-loss-prevention-outbound/intro.md +18 -0
  76. package/docs/policies/data-loss-prevention-outbound/schema.json +220 -0
  77. package/docs/policies/ip-restriction-inbound/policy.ts +1 -1
  78. package/docs/programmable-api/background-dispatcher.mdx +6 -8
  79. package/docs/programmable-api/http-problems.mdx +0 -18
  80. package/docs/programmable-api/jwt-service-plugin.mdx +131 -109
  81. package/docs/programmable-api/runtime-behaviors.mdx +4 -2
  82. package/docs/programmable-api/streaming-zone-cache.mdx +4 -6
  83. package/docs/programmable-api/web-crypto-apis.mdx +10 -6
  84. package/docs/programmable-api/zone-cache.mdx +1 -1
  85. package/docs/rate-limiting/combining-policies.mdx +293 -0
  86. package/docs/rate-limiting/dynamic-rate-limiting.mdx +240 -0
  87. package/docs/rate-limiting/getting-started.mdx +339 -0
  88. package/docs/rate-limiting/how-it-works.md +225 -0
  89. package/docs/rate-limiting/monitoring-and-troubleshooting.mdx +243 -0
  90. package/docs/{articles → rate-limiting}/per-user-rate-limits-using-db.mdx +39 -28
  91. package/package.json +4 -4
  92. package/docs/concepts/rate-limiting.md +0 -246
  93. package/docs/errors/get-head-body-error.mdx +0 -41
@@ -141,33 +141,40 @@ structured entries described above with their `event` field preserved.
141
141
  Registering both plugins is a small addition to `modules/zuplo.runtime.ts`:
142
142
 
143
143
  ```ts title="modules/zuplo.runtime.ts"
144
- import { RuntimeExtensions } from "@zuplo/runtime";
144
+ import { OpenTelemetryPlugin } from "@zuplo/otel";
145
+ import { environment, RuntimeExtensions } from "@zuplo/runtime";
145
146
  import { McpGatewayPlugin } from "@zuplo/runtime/mcp-gateway";
146
- import { OpenTelemetryPlugin } from "@zuplo/runtime";
147
147
 
148
148
  export function runtimeInit(runtime: RuntimeExtensions) {
149
149
  runtime.addPlugin(new McpGatewayPlugin());
150
150
  runtime.addPlugin(
151
151
  new OpenTelemetryPlugin({
152
- url: process.env.OTLP_TRACES_ENDPOINT,
153
- logUrl: process.env.OTLP_LOGS_ENDPOINT,
154
- authorization: process.env.OTLP_AUTHORIZATION,
152
+ traceUrl: environment.OTLP_TRACES_ENDPOINT,
153
+ logUrl: environment.OTLP_LOGS_ENDPOINT,
154
+ headers: {
155
+ Authorization: environment.OTLP_AUTHORIZATION,
156
+ },
157
+ service: {
158
+ name: "mcp-gateway",
159
+ },
155
160
  }),
156
161
  );
157
162
  }
158
163
  ```
159
164
 
160
- Grafana Cloud is one common destination define the endpoint and credentials in
161
- `.env`:
165
+ Logs are only exported when `logUrl` is set alongside `traceUrl` configuring
166
+ only `exporter.url` exports traces alone. Grafana Cloud is one common
167
+ destination — define the endpoints and credentials as
168
+ [environment variables](../../articles/environment-variables.mdx):
162
169
 
163
170
  ```bash
164
- GRAFANA_OTLP_ENDPOINT=https://otlp-gateway-prod-<region>.grafana.net/otlp
165
- GRAFANA_OTLP_INSTANCE_ID=<instance-id>
166
- GRAFANA_OTLP_API_TOKEN=glc_<token>
171
+ OTLP_TRACES_ENDPOINT=https://otlp-gateway-prod-<region>.grafana.net/otlp/v1/traces
172
+ OTLP_LOGS_ENDPOINT=https://otlp-gateway-prod-<region>.grafana.net/otlp/v1/logs
173
+ OTLP_AUTHORIZATION=Basic <base64 of instance-id:api-token>
167
174
  ```
168
175
 
169
- Use the base OTLP endpoint that ends in `/otlp` the runtime appends
170
- `/v1/traces` and `/v1/logs` itself. Other OTLP-compatible destinations
176
+ The plugin sends OTLP data to the configured URLs exactly as given, so include
177
+ the full `/v1/traces` and `/v1/logs` paths. Other OTLP-compatible destinations
171
178
  (Honeycomb, Dynatrace, New Relic, Tempo, self-hosted Jaeger) work the same way;
172
179
  substitute the endpoint and credential headers.
173
180
 
@@ -191,27 +191,36 @@ Response:
191
191
  "result": {
192
192
  "resources": [
193
193
  {
194
- "name": "html",
195
- "uri": "mcp://resources/html",
196
- "title": "html",
197
- "description": "Returns the AI applet's HTML",
198
- "mimeType": "text/plain"
194
+ "name": "html_doc",
195
+ "uri": "ui://html",
196
+ "title": "html_doc",
197
+ "description": "The HTML document for the AI applet",
198
+ "mimeType": "text/html"
199
199
  },
200
200
  {
201
- "name": "css_doc",
202
- "uri": "ui://css",
203
- "title": "css_doc",
204
- "description": "The CSS resource",
205
- "mimeType": "text/css"
201
+ "name": "css",
202
+ "uri": "mcp://resources/css",
203
+ "title": "css",
204
+ "description": "Returns the AI applet's CSS",
205
+ "mimeType": "text/plain"
206
206
  }
207
207
  ]
208
208
  }
209
209
  }
210
210
  ```
211
211
 
212
+ The `html_doc` resource uses the custom `name`, `uri`, `description`, and
213
+ `mimeType` from the route configuration shown earlier. The `css` resource sets
214
+ only `"mcp": { "type": "resource" }`, so the defaults apply: the name comes from
215
+ the `operationId`, the URI defaults to `mcp://resources/{name}`, the description
216
+ falls back to the operation's `description`, and the MIME type defaults to
217
+ `text/plain`.
218
+
212
219
  ### Read a Resource
213
220
 
214
- Use the MCP `resources/read` method to read a resource by its URI:
221
+ Use the MCP `resources/read` method to read a resource by its URI. Resources
222
+ configured without a custom `uri` use the default `mcp://resources/{name}`
223
+ format:
215
224
 
216
225
  ```bash
217
226
  curl https://my-gateway.zuplo.dev/mcp \
@@ -222,7 +231,7 @@ curl https://my-gateway.zuplo.dev/mcp \
222
231
  "id": "0",
223
232
  "method": "resources/read",
224
233
  "params": {
225
- "uri": "mcp://resources/html"
234
+ "uri": "mcp://resources/css"
226
235
  }
227
236
  }'
228
237
  ```
@@ -236,9 +245,9 @@ Response:
236
245
  "result": {
237
246
  "contents": [
238
247
  {
239
- "uri": "mcp://resources/html",
248
+ "uri": "mcp://resources/css",
240
249
  "mimeType": "text/plain",
241
- "text": "<div id=\"my-ai-applet\"></div>"
250
+ "text": "div { color: blue; }"
242
251
  }
243
252
  ]
244
253
  }
@@ -247,6 +256,9 @@ Response:
247
256
 
248
257
  ### Read a Resource with Custom URI
249
258
 
259
+ Resources configured with a custom `uri`, like the `html_doc` resource above,
260
+ are read using that URI:
261
+
250
262
  ```bash
251
263
  curl https://my-gateway.zuplo.dev/mcp \
252
264
  -X POST \
@@ -256,7 +268,7 @@ curl https://my-gateway.zuplo.dev/mcp \
256
268
  "id": "0",
257
269
  "method": "resources/read",
258
270
  "params": {
259
- "uri": "ui://css"
271
+ "uri": "ui://html"
260
272
  }
261
273
  }'
262
274
  ```
@@ -3,8 +3,6 @@ title: MCP Server Testing
3
3
  sidebar_label: Testing
4
4
  ---
5
5
 
6
- # Testing Tools
7
-
8
6
  ## Using MCP Inspector
9
7
 
10
8
  The [MCP Inspector](https://github.com/modelcontextprotocol/inspector) is ideal
@@ -37,6 +37,8 @@
37
37
  | curity-phantom-token-inbound | Curity Phantom Token Auth | Authenticate users using the Curity Phantom Token Pattern. | api-gateway |
38
38
  | custom-code-inbound | Custom Code Inbound | Enables a custom code policy written in TypeScript. Change YOUR_MODULE to the name of your module (without .ts extension) | api-gateway |
39
39
  | custom-code-outbound | Custom Code Outbound | A custom outbound response policy. | api-gateway |
40
+ | data-loss-prevention-outbound | Data Loss Prevention | Scans the upstream response body for sensitive data — PII, secrets, and financial identifiers — using an extensible catalog of built-in recognizers plus any custom patterns, and takes a configurable action when a match is found. The action is one of `mask` (redact matches before returning the response), `block` (replace the response with a `422` listing the detected entity names only), or `log` (record a warning and return unchanged). Only text content types are inspected; binary bodies pass through untouched, and the body is read from a clone so the client still receives the original stream. | api-gateway |
41
+ | data-loss-prevention-inbound | Data Loss Prevention | Scans the incoming request body for sensitive data — PII, secrets, and financial identifiers — using an extensible catalog of built-in recognizers plus any custom patterns, and takes a configurable action when a match is found. The action is one of `mask` (redact matches before forwarding the request), `block` (reject with a `422` listing the detected entity names only), or `log` (record a warning and forward unchanged). Only text content types are inspected; binary bodies pass through untouched, and the body is read from a clone so the upstream still receives the original stream. | api-gateway |
40
42
  | firebase-jwt-inbound | Firebase JWT Auth | Authenticate users using Firebase issued JWT tokens. | api-gateway |
41
43
  | formdata-to-json-inbound | Form Data to JSON | Converts form data in the incoming request to JSON. | api-gateway |
42
44
  | galileo-tracing-inbound | Galileo Tracing | Galileo Tracing Inbound Policy | ai-gateway |
@@ -20,7 +20,7 @@ can generate one of these on the `Shared access tokens` tab.
20
20
  Note, you should minimize the permissions - and select only the `Create`
21
21
  permission. Choose a sensible start and expiration time for your token. Note, we
22
22
  don't recommend restricting IP addresses because Zuplo runs at the edge in over
23
- 200 data-centers world-wide.
23
+ 300 data centers worldwide.
24
24
 
25
25
  ![Permissions](../../public/media/guides/archiving-requests-to-storage/Untitled_1.png)
26
26
 
@@ -20,7 +20,7 @@ can generate one of these on the `Shared access tokens` tab.
20
20
  Note, you should minimize the permissions - and select only the `Create`
21
21
  permission. Choose a sensible start and expiration time for your token. Note, we
22
22
  don't recommend restricting IP addresses because Zuplo runs at the edge in over
23
- 200 data-centers world-wide.
23
+ 300 data centers worldwide.
24
24
 
25
25
  ![Create permission](../../public/media/guides/archiving-requests-to-storage/Untitled_1.png)
26
26
 
@@ -0,0 +1,116 @@
1
+ This policy inspects the body of each incoming request for sensitive data and
2
+ applies a configurable action. It is the inbound counterpart to the
3
+ [Data Loss Prevention - Outbound](/docs/policies/data-loss-prevention-outbound)
4
+ policy, which inspects upstream responses.
5
+
6
+ Detection happens entirely inside the gateway isolate — request bodies are never
7
+ sent to a third-party service.
8
+
9
+ ## Actions
10
+
11
+ - **`mask`** (default) — every detected value is replaced with the `mask` string
12
+ and the modified body is forwarded upstream. Overlapping matches are merged
13
+ and masked once.
14
+ - **`block`** — the request is rejected with a `422 Unprocessable Content`. The
15
+ problem detail lists only the names of the detected entities, never the
16
+ matched values, so the policy never leaks the data it caught.
17
+ - **`log`** — a structured warning is written (entity ids and counts only) and
18
+ the request is forwarded unchanged.
19
+
20
+ ## Built-in recognizers
21
+
22
+ Enable entities individually or by **group selector** in the `entities`
23
+ option, or omit it to use the full catalog. Entity ids follow a
24
+ `{category}-{scope}-{name}` taxonomy, and any dash-aligned prefix of an id is a
25
+ valid selector: `secret` enables every secret, `id-au` enables Australia's
26
+ identifiers, `secret-aws` enables both AWS entities. Two named groups (`pii`,
27
+ `region-eu`) bundle entities across categories.
28
+
29
+ | Group | Entities |
30
+ | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
31
+ | `secret` | `secret-private-key`, `secret-jwt`, `secret-aws-access-key`, `secret-aws-bedrock`, `secret-github`, `secret-gitlab`, `secret-zuplo`, `secret-openai`, `secret-anthropic`, `secret-google-api-key`, `secret-stripe`, `secret-slack`, `secret-discord-webhook`, `secret-npm`, `secret-pypi`, `secret-sendgrid`, `secret-twilio`, `secret-hugging-face`, `secret-databricks`, `secret-shopify`, `secret-square`, `secret-mailchimp`, `secret-mailgun`, `secret-postman`, `secret-terraform`, `secret-sentry`, `secret-digitalocean`, `secret-heroku`, `secret-perplexity`, `secret-azure-client`, `secret-telegram-bot` |
32
+ | `finance` | `finance-credit-card` (Luhn), `finance-iban` (per-country length + mod-97), `finance-crypto-wallet`, `finance-us-aba-routing` (checksum), `finance-swift-bic`, `finance-us-bank-account`, `finance-cvv` |
33
+ | `id` | `id-us-ssn`, `id-us-itin`, `id-us-passport`, `id-uk-nino`, `id-uk-nhs` (mod-11), `id-ca-sin` (Luhn), `id-au-abn`, `id-au-acn`, `id-au-tfn`, `id-au-medicare` (all checksummed), `id-in-aadhaar` (Verhoeff), `id-in-pan`, `id-sg-nric` (checksum), `id-es-nif` (checksum), `id-it-fiscal-code` (checksum), `id-pl-pesel` (checksum), `id-nl-bsn` (11-proef), `id-br-cpf` (checksum), `id-fr-nir` (mod-97) |
34
+ | `contact` | `contact-email`, `contact-phone` |
35
+ | `network` | `network-ipv4`, `network-ipv6`, `network-mac` |
36
+ | `pii` | `contact` + `id` |
37
+ | Prefixes | `id-us`, `id-uk`, `id-au`, `id-ca`, `id-in`, `id-sg`, `id-es`, `id-it`, `id-pl`, `id-nl`, `id-br`, `id-fr`, `finance-us`, `secret-aws` — everything whose id starts with that prefix |
38
+ | `region-eu` | `id-es-nif`, `id-it-fiscal-code`, `id-pl-pesel`, `id-nl-bsn`, `id-fr-nir`, `finance-iban` |
39
+
40
+ ## Context-word scoring
41
+
42
+ Every match gets a confidence score. Recognizers whose raw pattern is just "a
43
+ run of digits" (bank accounts, routing numbers, NHS numbers, …) carry a low
44
+ base confidence and a list of **context words**; when one of those words
45
+ appears near the match — in prose, or in a JSON key, form field, or header-like
46
+ label (`nhsNumber`, `routing_number`, `cvv:`) — the confidence is boosted above
47
+ the detection threshold.
48
+
49
+ For example, with the `id-uk-nhs` entity enabled, `{"nhsNumber": "9434765919"}` is
50
+ masked while the same digits in `{"orderId": "9434765919"}` pass through
51
+ untouched.
52
+
53
+ The threshold is configurable via `minConfidence` (default `0.5`): lower it to
54
+ detect context-dependent entities everywhere, raise it to keep only prefix- and
55
+ checksum-validated matches.
56
+
57
+ ## Custom patterns
58
+
59
+ Add your own recognizers with `customPatterns`. Each entry has a `name`, a
60
+ JavaScript regular expression `pattern`, and optionally a `confidence` and
61
+ `context` words to participate in context scoring. Invalid patterns are logged
62
+ and skipped rather than failing the request. Remember to escape backslashes for
63
+ JSON (for example `\\d` to match a digit).
64
+
65
+ ## Content types
66
+
67
+ Only text-based bodies (JSON, XML, form-encoded, and `text/*`) are scanned;
68
+ binary bodies pass through untouched. Override the allow-list with the
69
+ `contentTypes` option if you need to scan a different set of content types.
70
+
71
+ ## Configuration
72
+
73
+ - `engine`: The detection engine. Only `builtin` is available today. **Default:**
74
+ `builtin`
75
+ - `entities`: Recognizer ids and/or group selectors (prefixes, `pii`,
76
+ `region-eu`) to enable. **Default:** all
77
+ recognizers
78
+ - `customPatterns`: Additional `{ name, pattern, confidence?, context? }` regex
79
+ recognizers
80
+ - `action`: `mask`, `block`, or `log`. **Default:** `mask`
81
+ - `mask`: Replacement string used when `action` is `mask`. **Default:**
82
+ `[REDACTED]`
83
+ - `minConfidence`: Detection threshold (0-1). **Default:** `0.5`
84
+ - `contentTypes`: Override the scannable content-type allow-list
85
+
86
+ ## Usage
87
+
88
+ Apply this policy to inbound requests in your route configuration:
89
+
90
+ ```json
91
+ {
92
+ "policies": [
93
+ {
94
+ "name": "data-loss-prevention-inbound",
95
+ "policyType": "data-loss-prevention-inbound",
96
+ "handler": {
97
+ "export": "DataLossPreventionInboundPolicy",
98
+ "module": "$import(@zuplo/runtime)",
99
+ "options": {
100
+ "action": "mask",
101
+ "entities": ["secret", "finance", "id-us", "contact-email"],
102
+ "mask": "[REDACTED]",
103
+ "customPatterns": [
104
+ {
105
+ "name": "employee-id",
106
+ "pattern": "EMP-\\d{6}",
107
+ "confidence": 0.3,
108
+ "context": ["employee"]
109
+ }
110
+ ]
111
+ }
112
+ }
113
+ }
114
+ ]
115
+ }
116
+ ```
@@ -0,0 +1,15 @@
1
+ The Data Loss Prevention (DLP) policy scans incoming request bodies for
2
+ sensitive data — personally identifiable information (PII), secrets and API
3
+ keys for dozens of vendors, payment and bank identifiers, and national IDs for
4
+ many countries — using a catalog of 60+ built-in recognizers plus any custom
5
+ patterns you add. When a match is found it takes a configurable action: mask
6
+ the matches, block the request, or log a warning and let it through.
7
+
8
+ Recognizers are selected individually or via entity groups (`secret`,
9
+ `finance`, `pii`, `id-us`, `id-uk`, `region-eu`, …). Detection runs entirely in the
10
+ gateway isolate using regular expressions, checksums (Luhn, mod-97, Verhoeff,
11
+ and friends), and context-word scoring — no request data leaves the gateway.
12
+
13
+ Pair with the
14
+ [Data Loss Prevention - Outbound](/docs/policies/data-loss-prevention-outbound)
15
+ policy to also scan upstream responses before they're returned to the client.
@@ -0,0 +1,220 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft-07/schema",
3
+ "$id": "https://cdn.zuplo.com/policies/runtime/schemas/data-loss-prevention-inbound.json",
4
+ "type": "object",
5
+ "title": "Data Loss Prevention",
6
+ "isDeprecated": false,
7
+ "isPaidAddOn": false,
8
+ "isEnterprise": false,
9
+ "isInternal": false,
10
+ "isBeta": false,
11
+ "isHidden": false,
12
+ "requiresAI": false,
13
+ "products": ["api-gateway"],
14
+ "description": "Scans the incoming request body for sensitive data — PII, secrets, and financial identifiers — using an extensible catalog of built-in recognizers plus any custom patterns, and takes a configurable action when a match is found.\n\nThe action is one of `mask` (redact matches before forwarding the request), `block` (reject with a `422` listing the detected entity names only), or `log` (record a warning and forward unchanged). Only text content types are inspected; binary bodies pass through untouched, and the body is read from a clone so the upstream still receives the original stream.",
15
+ "deprecatedMessage": "",
16
+ "required": ["handler"],
17
+ "properties": {
18
+ "handler": {
19
+ "type": "object",
20
+ "default": {},
21
+ "required": ["export", "module", "options"],
22
+ "properties": {
23
+ "export": {
24
+ "const": "DataLossPreventionInboundPolicy",
25
+ "description": "The name of the exported type"
26
+ },
27
+ "module": {
28
+ "const": "$import(@zuplo/runtime)",
29
+ "description": "The module containing the policy"
30
+ },
31
+ "options": {
32
+ "title": "DataLossPreventionInboundPolicyOptions",
33
+ "type": "object",
34
+ "description": "The options for the Data Loss Prevention inbound policy. Scans the incoming request body for sensitive data and applies the configured action (mask, block, or log).",
35
+ "additionalProperties": false,
36
+ "required": [],
37
+ "examples": [
38
+ {
39
+ "action": "mask",
40
+ "entities": ["secret", "finance", "contact-email", "id-us-ssn"],
41
+ "mask": "[REDACTED]"
42
+ }
43
+ ],
44
+ "properties": {
45
+ "engine": {
46
+ "type": "string",
47
+ "enum": ["builtin"],
48
+ "default": "builtin",
49
+ "description": "The detection engine. Only `builtin` (in-isolate regex + checksum detection with context-word scoring) is available today. This is the extension point for a future hosted `presidio-service` mode; declaring it now keeps adding that mode an additive, non-breaking change."
50
+ },
51
+ "entities": {
52
+ "type": "array",
53
+ "description": "Built-in recognizer ids and/or group selectors to enable. Entity ids follow a {category}-{scope}-{name} taxonomy, and any dash-aligned id prefix acts as a selector (for example `secret` is every secret, `id-au` is Australia's identifiers, `secret-aws` is both AWS entities), plus the named groups `pii` and `region-eu`. Available selectors: `contact`, `finance`, `finance-us`, `id`, `id-au`, `id-br`, `id-ca`, `id-es`, `id-fr`, `id-in`, `id-it`, `id-nl`, `id-pl`, `id-sg`, `id-uk`, `id-us`, `network`, `pii`, `region-eu`, `secret`, `secret-aws`. When omitted, the full built-in catalog is used.",
54
+ "items": {
55
+ "type": "string",
56
+ "enum": [
57
+ "contact",
58
+ "finance",
59
+ "finance-us",
60
+ "id",
61
+ "id-au",
62
+ "id-br",
63
+ "id-ca",
64
+ "id-es",
65
+ "id-fr",
66
+ "id-in",
67
+ "id-it",
68
+ "id-nl",
69
+ "id-pl",
70
+ "id-sg",
71
+ "id-uk",
72
+ "id-us",
73
+ "network",
74
+ "pii",
75
+ "region-eu",
76
+ "secret",
77
+ "secret-aws",
78
+ "contact-email",
79
+ "contact-phone",
80
+ "finance-credit-card",
81
+ "finance-crypto-wallet",
82
+ "finance-cvv",
83
+ "finance-iban",
84
+ "finance-swift-bic",
85
+ "finance-us-aba-routing",
86
+ "finance-us-bank-account",
87
+ "id-au-abn",
88
+ "id-au-acn",
89
+ "id-au-medicare",
90
+ "id-au-tfn",
91
+ "id-br-cpf",
92
+ "id-ca-sin",
93
+ "id-es-nif",
94
+ "id-fr-nir",
95
+ "id-in-aadhaar",
96
+ "id-in-pan",
97
+ "id-it-fiscal-code",
98
+ "id-nl-bsn",
99
+ "id-pl-pesel",
100
+ "id-sg-nric",
101
+ "id-uk-nhs",
102
+ "id-uk-nino",
103
+ "id-us-itin",
104
+ "id-us-passport",
105
+ "id-us-ssn",
106
+ "network-ipv4",
107
+ "network-ipv6",
108
+ "network-mac",
109
+ "secret-anthropic",
110
+ "secret-aws-access-key",
111
+ "secret-aws-bedrock",
112
+ "secret-azure-client",
113
+ "secret-databricks",
114
+ "secret-digitalocean",
115
+ "secret-discord-webhook",
116
+ "secret-github",
117
+ "secret-gitlab",
118
+ "secret-google-api-key",
119
+ "secret-heroku",
120
+ "secret-hugging-face",
121
+ "secret-jwt",
122
+ "secret-mailchimp",
123
+ "secret-mailgun",
124
+ "secret-npm",
125
+ "secret-openai",
126
+ "secret-perplexity",
127
+ "secret-postman",
128
+ "secret-private-key",
129
+ "secret-pypi",
130
+ "secret-sendgrid",
131
+ "secret-sentry",
132
+ "secret-shopify",
133
+ "secret-slack",
134
+ "secret-square",
135
+ "secret-stripe",
136
+ "secret-telegram-bot",
137
+ "secret-terraform",
138
+ "secret-twilio",
139
+ "secret-zuplo"
140
+ ]
141
+ }
142
+ },
143
+ "customPatterns": {
144
+ "type": "array",
145
+ "description": "Additional customer-defined regex recognizers. Invalid patterns are logged and skipped rather than failing the request.",
146
+ "items": {
147
+ "type": "object",
148
+ "title": "DlpCustomPattern",
149
+ "additionalProperties": false,
150
+ "required": ["name", "pattern"],
151
+ "properties": {
152
+ "name": {
153
+ "type": "string",
154
+ "description": "Identifier reported in findings and block details for this pattern."
155
+ },
156
+ "pattern": {
157
+ "type": "string",
158
+ "description": "A JavaScript regular expression source string. Remember to escape backslashes for JSON (for example `\\\\d` for a digit)."
159
+ },
160
+ "confidence": {
161
+ "type": "number",
162
+ "minimum": 0,
163
+ "maximum": 1,
164
+ "default": 0.85,
165
+ "description": "Base confidence (0-1) for matches of this pattern. The default of 0.85 is above the default detection threshold; combine a low value with `context` words for patterns that are only sensitive in context."
166
+ },
167
+ "context": {
168
+ "type": "array",
169
+ "items": {
170
+ "type": "string"
171
+ },
172
+ "description": "Context words that boost a match's confidence by 0.45 when one appears near the match (in the surrounding field, label, or key)."
173
+ }
174
+ }
175
+ }
176
+ },
177
+ "action": {
178
+ "type": "string",
179
+ "enum": ["mask", "block", "log"],
180
+ "default": "mask",
181
+ "description": "What to do when sensitive data is detected. `mask` redacts matches before forwarding the request, `block` rejects with a 422 listing only the detected entity names, and `log` records a warning and forwards the request unchanged."
182
+ },
183
+ "mask": {
184
+ "type": "string",
185
+ "default": "[REDACTED]",
186
+ "examples": ["[REDACTED]"],
187
+ "description": "The string that replaces detected values when `action` is `mask`."
188
+ },
189
+ "minConfidence": {
190
+ "type": "number",
191
+ "minimum": 0,
192
+ "maximum": 1,
193
+ "default": 0.5,
194
+ "x-show-example": false,
195
+ "description": "Minimum confidence (0-1) a match must reach to count as a finding. Context-dependent recognizers (for example `finance-us-bank-account` or `finance-us-aba-routing`) sit below the default threshold of 0.5 until a context word near the match boosts them above it. Lower the threshold to surface them everywhere; raise it to keep only prefix- or checksum-validated matches."
196
+ },
197
+ "contentTypes": {
198
+ "type": "array",
199
+ "description": "Override the set of scannable content-type prefixes. When omitted, the built-in text content-type allow-list (JSON, XML, form-encoded, text/\\*) is used.",
200
+ "items": {
201
+ "type": "string"
202
+ }
203
+ }
204
+ }
205
+ }
206
+ },
207
+ "examples": [
208
+ {
209
+ "export": "DataLossPreventionInboundPolicy",
210
+ "module": "$import(@zuplo/runtime)",
211
+ "options": {
212
+ "action": "mask",
213
+ "entities": ["secret", "finance", "contact-email", "id-us-ssn"],
214
+ "mask": "[REDACTED]"
215
+ }
216
+ }
217
+ ]
218
+ }
219
+ }
220
+ }