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
@@ -0,0 +1,73 @@
1
+ ---
2
+ title: "Consumers"
3
+ sidebar_label: "Consumers"
4
+ ---
5
+
6
+ The **Consumers** tab breaks traffic down by API consumer: anyone calling your
7
+ gateway, whether authenticated or anonymous. Use it to see who your noisiest
8
+ callers are, who's hitting errors, and which consumers experience the slowest
9
+ latency.
10
+
11
+ ## When to use this
12
+
13
+ - Find the top API consumers by request volume.
14
+ - Identify which consumer is responsible for a 4xx or 5xx surge.
15
+ - Compare latency experience across consumers (for example, paid vs free tier).
16
+
17
+ ## Summary KPIs
18
+
19
+ | Name | What it measures |
20
+ | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
21
+ | **Requests** | Total requests across all consumers in the window. |
22
+ | **Client Errors** | Request-weighted 4xx rate across consumers (high-traffic consumers count more). See [Metrics glossary](../reference/metrics-glossary.md). |
23
+ | **Server Errors** | Request-weighted 5xx rate. Secondary: count of consumers with at least one 5xx. |
24
+ | **Consumers** | Distinct consumers (authenticated plus anonymous). |
25
+ | **Total Errors** | Combined 4xx + 5xx count. Secondary: consumers affected. |
26
+
27
+ ## Charts
28
+
29
+ **Request Volume.** Stacked bars by status class. The chart title updates to
30
+ reflect the active consumer filter so you can tell at a glance whether you're
31
+ looking at one consumer or all of them.
32
+
33
+ **Consumer Error Rates.** 4xx and 5xx over time. _What to look for:_ a sustained
34
+ 4xx rate from one consumer usually points to a broken integration on their side.
35
+
36
+ **Consumer Latency Over Time.** P50, P95, P99 lines.
37
+
38
+ ## Consumer table
39
+
40
+ | Column | Notes |
41
+ | --------------- | ------------------------------------------------------------------- |
42
+ | User | Consumer identity. Anonymous requests show **Anonymous · No auth**. |
43
+ | Requests | Count with an inline volume bar. |
44
+ | Client Errors % | 4xx percentage. |
45
+ | Server Errors % | 5xx percentage. |
46
+ | Avg / P95 / P99 | Latency percentiles. |
47
+ | 4xx sparkline | Inline trend over the window. |
48
+ | 5xx sparkline | Inline trend over the window. |
49
+
50
+ The table is searchable and sortable on any column (default: requests
51
+ descending). Clicking a row filters the entire tab to that consumer. **Show
52
+ more** loads the next 50.
53
+
54
+ ## Filters
55
+
56
+ The filter bar applies. `originHost` is not applicable on this tab. See
57
+ [Shared controls](../shared-controls.md#filters).
58
+
59
+ ## Troubleshooting
60
+
61
+ **Everything is showing as Anonymous.** If your gateway isn't authenticating
62
+ requests, or your auth policy isn't attaching a consumer identity, every request
63
+ falls into the **Anonymous · No auth** bucket. Check your API key or JWT policy
64
+ configuration.
65
+
66
+ **I clicked a row but the charts didn't change.** A row click adds a consumer
67
+ filter pill. If you don't see the pill in the sticky bar, your click landed on a
68
+ non-row element. Try clicking the user cell directly.
69
+
70
+ **The 5xx rate here is higher than on Requests.** The Consumers KPI is
71
+ request-weighted across consumers, while the Requests KPI is a flat rate over
72
+ all requests. They diverge when high-error consumers are a small share of total
73
+ volume. See [Metrics glossary](../reference/metrics-glossary.md).
@@ -0,0 +1,77 @@
1
+ ---
2
+ title: "GraphQL"
3
+ sidebar_label: "GraphQL"
4
+ ---
5
+
6
+ The **GraphQL** tab breaks traffic down by GraphQL operation: the queries,
7
+ mutations, and subscriptions clients send through routes you've marked as
8
+ GraphQL endpoints. Use it to find your most-used operations, separate validation
9
+ and resolver errors, and see how much of each operation's latency falls in your
10
+ upstream resolvers. It's visible when the project proxies a GraphQL API.
11
+
12
+ ## When to use this
13
+
14
+ - Find the highest-volume operations and the ones clients call most.
15
+ - Separate resolver, validation, and auth errors when a GraphQL endpoint
16
+ misbehaves.
17
+ - Compare total round-trip latency against resolver-only time to see whether the
18
+ gateway or the upstream owns a slowdown.
19
+
20
+ ## Summary KPIs
21
+
22
+ | Name | What it measures |
23
+ | ----------------- | --------------------------------------------------------------------------------------------- |
24
+ | **Operations** | Total GraphQL operations in the window. |
25
+ | **Success Rate** | Share of operations that completed without error. Secondary: ok / err split. |
26
+ | **p95 Latency** | Total P95 across operations. Secondary: resolver P95. |
27
+ | **Error Classes** | Total errored operations. Secondary: resolver / validation / auth split (`res · val · auth`). |
28
+
29
+ See [Metrics glossary](../reference/metrics-glossary.md) for error-class and
30
+ resolver-latency definitions.
31
+
32
+ ## Charts
33
+
34
+ **GraphQL Operations Over Time.** Operation volume per interval. Populates once
35
+ a client sends a query, mutation, or subscription.
36
+
37
+ **Operation Types.** A donut splitting operations across **query**,
38
+ **mutation**, and **subscription**.
39
+
40
+ **Latency — Total vs Resolver.** Total P95 and resolver P95 over time, with P50
41
+ total, P95 total, P99 total, and P95 resolver summary cards. _What to look for:_
42
+ a total P95 well above the resolver P95 means the operation spends its time
43
+ outside your resolvers — in parsing, validation, or gateway policies — rather
44
+ than in the upstream.
45
+
46
+ ## Operations table
47
+
48
+ | Column | Notes |
49
+ | -------------------- | ---------------------------------------------- |
50
+ | Operation | The GraphQL operation name. |
51
+ | Type | query, mutation, or subscription. |
52
+ | Operations | Count with an inline volume bar. |
53
+ | Errors | Errored-operation count. |
54
+ | Error Rate | Errors ÷ operations. |
55
+ | Complexity (avg/max) | Average and maximum computed query complexity. |
56
+ | p95 | P95 latency for the operation. |
57
+
58
+ The table is searchable and sortable on any column (default: operations
59
+ descending).
60
+
61
+ ## Filters
62
+
63
+ The filter bar applies. See [Shared controls](../shared-controls.md#filters).
64
+
65
+ ## Troubleshooting
66
+
67
+ **The GraphQL tab is empty.** No GraphQL operations arrived in the selected
68
+ window. Operations appear once a client sends a query, mutation, or subscription
69
+ through a route you've marked as a GraphQL endpoint. See
70
+ [GraphQL on Zuplo](../../articles/graphql.mdx) for how to mark a route.
71
+
72
+ **The tab isn't visible.** Visibility requires at least one route you've marked
73
+ as a GraphQL endpoint. See [GraphQL on Zuplo](../../articles/graphql.mdx).
74
+
75
+ **Total latency is high but resolver latency is low.** The operation spends its
76
+ time outside your resolvers. Check the gateway policies on the GraphQL route —
77
+ parsing, validation, complexity analysis, or auth — rather than the upstream.
@@ -0,0 +1,80 @@
1
+ ---
2
+ title: "MCP"
3
+ sidebar_label: "MCP"
4
+ ---
5
+
6
+ The **MCP** tab shows Model Context Protocol traffic through Zuplo: OAuth and
7
+ auth decisions, virtual-server routing, capability and tool invocations,
8
+ JSON-RPC method usage, and upstream MCP server health. It covers both traffic
9
+ that flows _to_ an MCP fleet through Zuplo's gateway and activity _inside_ MCP
10
+ servers you host on Zuplo. It's visible when the project type is **standard**
11
+ and MCP is in use.
12
+
13
+ ## When to use this
14
+
15
+ - See which virtual servers, capabilities, and tools clients call most, and
16
+ who's calling them.
17
+ - Track auth and policy decision outcomes across OAuth flows.
18
+ - Identify whether failures originate in the gateway, the upstream, or the
19
+ client.
20
+ - Investigate the JSON-RPC error codes clients receive.
21
+
22
+ ## Summary KPIs
23
+
24
+ | Name | What it measures |
25
+ | ----------------------- | -------------------------------------------------------------------------------------------- |
26
+ | **Events** | Total MCP events in the window. |
27
+ | **Success Rate** | Share of events with outcome = success. Secondary: success / error split. |
28
+ | **Client Errors (4xx)** | Count of client-side errors. Secondary: share of all errors. |
29
+ | **Server Errors (5xx)** | Count of server-side errors. Secondary: share of all errors. |
30
+ | **Failure Origins** | Combined gateway + upstream + client failures. Secondary: per-origin split (`gw · up · cl`). |
31
+
32
+ See [Metrics glossary](../reference/metrics-glossary.md) for the failure-origin
33
+ and outcome-class definitions.
34
+
35
+ ## Charts
36
+
37
+ **MCP Events Over Time.** Stacked area showing the top event types over the
38
+ window.
39
+
40
+ **Event Families.** A donut distributing events across families: **Requests**,
41
+ **Capabilities**, and **Auth**.
42
+
43
+ **Latency — Gateway vs Upstream.** Total, gateway, and upstream P95 over time,
44
+ with P50 total, P95 total, P95 gateway, and P95 upstream summary cards. _What to
45
+ look for:_ a P95 that the upstream slice dominates points to a slow MCP backend;
46
+ a gateway-heavy P95 points to policy or auth overhead.
47
+
48
+ ## Breakdown tables
49
+
50
+ | Table | Columns |
51
+ | -------------------- | ---------------------------------------------------------------------------------------------------------------------- |
52
+ | Capabilities | Server, Capability, Type, Calls, Client (4xx), Server (5xx), Error Rate, P95. |
53
+ | Consumers | Consumer, Events, Client (4xx), Server (5xx). |
54
+ | Virtual Servers | Virtual Server, Events, Client (4xx), Server (5xx). |
55
+ | Upstream Servers | Upstream, Events, Client (4xx), Server (5xx), P95. |
56
+ | MCP Methods | Method (for example `tools/call`, `tools/list`, `resources/list`, `prompts/list`, `resources/templates/list`), Events. |
57
+ | Clients | Client, Kind (from the `initialize` handshake), Events. |
58
+ | JSON-RPC Error Codes | Code, Errors — the JSON-RPC error codes clients receive. |
59
+ | Failure Origins | Origin (gateway / upstream / client), Errors, Client (4xx), Server (5xx). |
60
+ | Reason Codes | Class, Code, Events, Errors, Client (4xx), Server (5xx). |
61
+
62
+ Most tables sort on any column and show the top values by volume. Click **Show
63
+ more** to load the next page.
64
+
65
+ ## Filters
66
+
67
+ The filter bar applies. See [Shared controls](../shared-controls.md#filters).
68
+
69
+ ## Troubleshooting
70
+
71
+ **The MCP tab is empty.** No MCP events arrived in the selected window. Once a
72
+ client connects and invokes a capability or tool, the dashboard populates.
73
+
74
+ **The tab isn't visible.** Visibility requires project type **standard** with
75
+ MCP in use — either an MCP gateway that routes to upstream servers, or an MCP
76
+ server you host on Zuplo.
77
+
78
+ **Errors show but Failure Origins is empty.** Zuplo classifies failure origins
79
+ server-side from event metadata. Events without a clear origin classification
80
+ land in Errors but in none of the gateway / upstream / client buckets.
@@ -0,0 +1,82 @@
1
+ ---
2
+ title: "Origins"
3
+ sidebar_label: "Origins"
4
+ ---
5
+
6
+ The **Origins** tab shows backend performance: how each upstream host you proxy
7
+ to is performing in terms of volume, error rate, and latency. It's visible when
8
+ the project uses managed-edge origins.
9
+
10
+ ## When to use this
11
+
12
+ - Identify which backend is slow or returning errors.
13
+ - Compare the latency contribution of DNS, TCP, TLS, and application time.
14
+ - Audit traffic distribution across direct origins and service tunnels.
15
+
16
+ ## Summary metrics
17
+
18
+ The header strip shows totals derived from the time series:
19
+
20
+ | Name | What it measures |
21
+ | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
22
+ | Total requests | All requests served against any origin in the window. |
23
+ | 4xx rate | Client error rate across all origins. |
24
+ | 5xx rate | Server error rate across all origins. |
25
+ | Weighted avg latency | Origin response time weighted by request count, so high-traffic origins dominate. See [Metrics glossary](../reference/metrics-glossary.md). |
26
+
27
+ ## Charts
28
+
29
+ **Backend Request Time Series.** Stacked bars by status class, aggregated across
30
+ origins by default. Apply a host filter to scope to one origin.
31
+
32
+ **Backend Latency.** Average and P95 over time. _What to look for:_ a P95 climb
33
+ while the average stays flat usually points to a few slow origins or routes
34
+ inside an otherwise healthy fleet.
35
+
36
+ **Backend Error Rate.** 4xx and 5xx rates over time.
37
+
38
+ **Request Lifecycle.** Stacked time spent in each phase of an origin request:
39
+ **DNS time**, **TCP time**, **TLS time**, and **application time**. A high TLS
40
+ slice indicates handshake overhead; a high application slice indicates the
41
+ origin is slow.
42
+
43
+ ## Tables
44
+
45
+ Two tables sit side by side in a 2-column grid.
46
+
47
+ ### Direct Origins
48
+
49
+ | Column | Notes |
50
+ | --------------- | -------------------------------- |
51
+ | Host | The origin hostname. |
52
+ | Requests | Count with an inline volume bar. |
53
+ | Client Errors | 4xx percentage. |
54
+ | Server Errors | 5xx percentage. |
55
+ | Avg / P95 / P99 | Latency percentiles. |
56
+ | 4xx sparkline | Inline trend over the window. |
57
+ | 5xx sparkline | Inline trend over the window. |
58
+
59
+ Clicking a row toggles a host filter. Click again to remove it.
60
+
61
+ ### Service Tunnels
62
+
63
+ Same columns and behavior as Direct Origins, scoped to tunnel-routed origins.
64
+ The table is hidden when no tunnel traffic is present.
65
+
66
+ ## Filters
67
+
68
+ The filter bar applies, with one exception: `userSub` is not applicable on this
69
+ tab. See [Shared controls](../shared-controls.md#filters).
70
+
71
+ ## Troubleshooting
72
+
73
+ **The Origins tab isn't visible.** It appears only when the project uses
74
+ managed-edge origins. If your project routes traffic differently, the tab is
75
+ hidden.
76
+
77
+ **Service Tunnels table is missing.** That table only renders when at least one
78
+ origin is reached over a service tunnel.
79
+
80
+ **A 5xx spike on one origin doesn't match the Requests tab.** If you've filtered
81
+ the Requests tab to a different route or status class, totals won't match. Clear
82
+ filters or compare with the same filters applied on both tabs.
@@ -0,0 +1,96 @@
1
+ ---
2
+ title: "Requests"
3
+ sidebar_label: "Requests"
4
+ ---
5
+
6
+ The **Requests** tab is the default Analytics overview: every request through
7
+ your gateway in the selected time window, with charts and breakdowns for volume,
8
+ latency, and errors.
9
+
10
+ ## When to use this
11
+
12
+ - Spot-check overall traffic and error rate across a project or the whole
13
+ account.
14
+ - Investigate a spike in 4xx or 5xx responses.
15
+ - Drill from a route, status code, or geographic breakdown into the underlying
16
+ requests.
17
+
18
+ ## Summary KPIs
19
+
20
+ | Name | What it measures | When it's useful |
21
+ | ----------------- | ------------------------------------------------------------- | ----------------------------------------- |
22
+ | **Requests** | Total request count. Secondary value: successful (2xx) count. | Quick health check on volume and success. |
23
+ | **Client Errors** | 4xx rate (4xx ÷ total). Secondary value: raw 4xx count. | Spot bad-input or auth issues. |
24
+ | **Server Errors** | 5xx rate (5xx ÷ total). Secondary value: raw 5xx count. | Spot gateway or upstream failures. |
25
+ | **Avg Latency** | Mean response time. Secondary value: min to max. | Detect broad latency regressions. |
26
+ | **Consumers** | Distinct API consumers (authenticated + anonymous). | Gauge active audience. |
27
+
28
+ See [Metrics glossary](../reference/metrics-glossary.md) for how rates and
29
+ percentiles are computed.
30
+
31
+ ## Charts
32
+
33
+ **Request Time Series.** Stacked bars per interval, broken down by status class
34
+ (2xx / 3xx / 4xx / 5xx). Drag to select a region to zoom; the time range picker
35
+ updates to match.
36
+
37
+ **Request Locations Map.** A world map with a heatmap of request volume by
38
+ location. Shown only when geolocation data is present.
39
+
40
+ **Latency Over Time.** P50, P95, and P99 lines. _What to look for:_ a widening
41
+ gap between P50 and P95 typically signals a tail-latency problem affecting a
42
+ subset of requests.
43
+
44
+ **Error Rate.** 4xx and 5xx rates plotted over time.
45
+
46
+ **Latency Distribution.** A histogram of P10, P50, P90, P95, and P99 buckets.
47
+ Click a band to filter the rest of the tab to requests in that duration range.
48
+
49
+ **Active Instances.** Distinct active edge instances over time. A rough
50
+ indicator of how widely your traffic is distributed across gateway workers.
51
+
52
+ ## Breakdowns
53
+
54
+ Each breakdown shows the top 10 values by request count. Click **Show more** to
55
+ load the next 50.
56
+
57
+ **Primary breakdowns:**
58
+
59
+ - **HTTP Method**
60
+ - **HTTP Status**
61
+ - **Route Path**
62
+
63
+ **Account scope only:**
64
+
65
+ - **Project Name**: click to drill into project-scope analytics.
66
+ - **Deployment Name**: click to drill into a specific deployment.
67
+
68
+ **Secondary breakdowns:**
69
+
70
+ - **Country**, **City**, **Colo**
71
+ - **User Sub**
72
+ - **Client IP**
73
+ - **AS Organization**
74
+
75
+ Clicking any value applies an `equals` filter for that field.
76
+
77
+ ## Filters
78
+
79
+ The full filter bar applies. `originHost` is not applicable on this tab. See
80
+ [Shared controls](../shared-controls.md#filters) for match modes and the filter
81
+ pill UI.
82
+
83
+ ## Troubleshooting
84
+
85
+ **The map is missing.** The Request Locations Map only renders when geolocation
86
+ data is present in the time window. Short windows for low-traffic projects may
87
+ not include any geolocated requests.
88
+
89
+ **Show more doesn't load anything.** You may already be viewing every value for
90
+ that breakdown. Top-10 plus 50 covers up to 60 distinct values; beyond that,
91
+ narrow the time range or add a filter.
92
+
93
+ **My charts look sparse.** If your account is new, the trial banner across the
94
+ top calls this out. Click **View demo →** in the banner to see what a fully
95
+ populated dashboard looks like. See
96
+ [Access and entitlements](../access-and-entitlements.md).
@@ -11,10 +11,12 @@ credentials across different environments. Learn more in the
11
11
 
12
12
  Zuplo automatically creates three buckets for each project:
13
13
 
14
- - **Working copy**: Stores API keys for the working-copy environment
15
14
  - **Production**: Stores API keys for the production environment (your default
16
15
  Git branch)
17
- - **Shared**: Stores API keys shared across all other environments
16
+ - **Preview**: Stores API keys shared across all preview environments
17
+ (non-default Git branches)
18
+ - **Development**: Stores API keys for the development (working copy)
19
+ environment
18
20
 
19
21
  For more information on how environments relate to Git branches, see
20
22
  [Branch-Based Deployments](./branch-based-deployments.mdx).
@@ -30,7 +30,7 @@ can generate one of these on the `Shared access tokens` tab.
30
30
  Note, you should minimize the permissions - and select only the `Create`
31
31
  permission. Choose a sensible start and expiration time for your token. Note, we
32
32
  don't recommend restricting IP addresses because Zuplo runs at the edge in over
33
- 200 data-centers world-wide.
33
+ 300 data centers worldwide.
34
34
 
35
35
  ![shared access tokens](../../public/media/guides/archiving-requests-to-storage/Untitled_1.png)
36
36
 
@@ -46,7 +46,7 @@ You'll need another environment variable called `BLOB_CONTAINER_PATH`.
46
46
  We'll write a policy called `request-archive-policy` that can be used on all
47
47
  routes.
48
48
 
49
- ```ts title="file-archive-policy.ts"
49
+ ```ts title="modules/request-archive-policy.ts"
50
50
  import { ZuploRequest, ZuploContext } from "@zuplo/runtime";
51
51
 
52
52
  export type RequestArchivePolicyOptions = {
@@ -102,7 +102,7 @@ example below:
102
102
  "policyType": "code-policy",
103
103
  "handler": {
104
104
  "export": "default",
105
- "module": "$import(./modules/archive-request-policy)",
105
+ "module": "$import(./modules/request-archive-policy)",
106
106
  "options": {
107
107
  "blobCreateSas": "$env(BLOB_CREATE_SAS)",
108
108
  "blobContainerPath": "$env(BLOB_CONTAINER_PATH)"
@@ -111,7 +111,7 @@ example below:
111
111
  }
112
112
  ```
113
113
 
114
- Don't forget to reference the `file-archive-policy` in the policies.inbound
114
+ Don't forget to reference the `request-archive-policy` in the policies.inbound
115
115
  property of your routes.
116
116
 
117
117
  Here's the policy in action:
@@ -34,17 +34,19 @@ bugfix/123 ─────────────────► Preview (b
34
34
  When Zuplo deploys an environment from a branch, the environment name matches
35
35
  the branch name. For example:
36
36
 
37
- | Branch Name | Environment Name | Example URL |
38
- | -------------- | ---------------- | --------------------------------------------------- |
39
- | `main` | main | `https://my-project-main-abc1234.zuplo.app` |
40
- | `staging` | staging | `https://my-project-staging-def5678.zuplo.app` |
41
- | `feature/auth` | feature/auth | `https://my-project-feature-auth-ghi9012.zuplo.app` |
37
+ | Branch Name | Environment Name | Example URL |
38
+ | -------------- | ---------------- | ------------------------------------------------- |
39
+ | `main` | main | `https://my-project-main-abc1234.zuplo.app` |
40
+ | `staging` | staging | `https://my-project-staging-def5678.zuplo.app` |
41
+ | `feature/auth` | feature/auth | `https://my-project-feature-au-ghi9012.zuplo.app` |
42
42
 
43
43
  :::note
44
44
 
45
- The environment URL includes a unique identifier to ensure each deployment has a
46
- distinct address. Configure [custom domains](./custom-domains.mdx) for your
47
- environments.
45
+ Zuplo normalizes the branch name in the deployment URL lowercasing it,
46
+ replacing special characters with hyphens, and truncating it to 10 characters —
47
+ which is why `feature/auth` appears as `feature-au`. The URL also includes a
48
+ unique identifier to ensure each deployment has a distinct address. Configure
49
+ [custom domains](./custom-domains.mdx) for your environments.
48
50
 
49
51
  :::
50
52
 
@@ -27,7 +27,9 @@ jobs:
27
27
  run: npm install
28
28
 
29
29
  - name: Deploy to Zuplo
30
- run: npx zuplo deploy --api-key "$ZUPLO_API_KEY"
30
+ run:
31
+ npx zuplo deploy --api-key "$ZUPLO_API_KEY" --environment "${{
32
+ github.ref_name }}"
31
33
  env:
32
34
  ZUPLO_API_KEY: ${{ secrets.ZUPLO_API_KEY }}
33
35
  ```
@@ -41,6 +43,13 @@ This workflow:
41
43
 
42
44
  Since this deploys from `main`, it updates your production environment.
43
45
 
46
+ Passing `--environment` is technically optional here — without it, the CLI
47
+ infers the environment name from the checked-out git ref — but inference can
48
+ pick the wrong name in CI (detached HEAD checkouts, commits that exist on more
49
+ than one branch, or `pull_request` merge refs). Passing the branch name
50
+ explicitly makes every workflow deploy a predictable environment. See the
51
+ [deploy command reference](../../cli/deploy.mdx) for details.
52
+
44
53
  ## Next Steps
45
54
 
46
55
  - Add [testing after deployment](./deploy-and-test.mdx)
@@ -34,24 +34,29 @@ jobs:
34
34
  run: |
35
35
  # The deleted branch name
36
36
  BRANCH_NAME="${{ github.event.ref }}"
37
- # Convert slashes to hyphens
38
- ENV_NAME="${BRANCH_NAME//\//-}"
39
-
40
- echo "Deleting environment: $ENV_NAME"
41
-
42
- # Ignore errors if env doesn't exist
43
- npx zuplo delete \
44
- --environment "$ENV_NAME" \
45
- --api-key "$ZUPLO_API_KEY" \
46
- --wait || true
37
+ # Deployment names use the format {project}-{branch}-{hash}, where
38
+ # the branch segment is normalized (lowercase, special characters
39
+ # replaced by hyphens) and truncated to 10 characters
40
+ ENV_NAME=$(echo "$BRANCH_NAME" | tr '/_' '--' |
41
+ tr '[:upper:]' '[:lower:]' | cut -c1-10 | sed 's/-*$//')
42
+
43
+ # Find the deployment for the deleted branch and delete it by URL
44
+ npx zuplo list --api-key "$ZUPLO_API_KEY" \
45
+ --output json --show-details |
46
+ jq -r --arg env "$ENV_NAME" \
47
+ '.[] | select(.name | test("-" + $env + "-[a-z0-9]+$")) | .url' |
48
+ while read -r URL; do
49
+ echo "Deleting environment: $URL"
50
+ npx zuplo delete --url "$URL" --api-key "$ZUPLO_API_KEY" --wait || true
51
+ done
47
52
  ```
48
53
 
49
54
  This workflow:
50
55
 
51
56
  1. Triggers when any branch is deleted
52
- 2. Converts the branch name to the environment name format
53
- 3. Deletes the corresponding Zuplo environment
54
- 4. Continues without error if the environment doesn't exist
57
+ 2. Converts the branch name to the deployment-name branch segment format
58
+ 3. Looks up the matching deployment and deletes it by URL
59
+ 4. Continues without error if no matching environment exists
55
60
 
56
61
  ## Combining with PR Cleanup
57
62
 
@@ -95,24 +100,40 @@ jobs:
95
100
 
96
101
  - name: Cleanup stale environments
97
102
  run: |
98
- # Get all remote branches
99
- BRANCHES=$(git branch -r | sed 's|origin/||' | tr '/' '-' | tr -d ' ')
100
-
101
- # List Zuplo environments and delete stale ones
102
- npx zuplo list --api-key "$ZUPLO_API_KEY" --json > environments.json
103
-
104
- cat environments.json | jq -r '.[] | .name' | while read ENV; do
105
- # Skip protected environments
106
- if [[ "$ENV" == "main" || "$ENV" == "production" || "$ENV" == "staging" ]]; then
107
- continue
108
- fi
109
-
110
- # Delete if no matching branch exists
111
- if ! echo "$BRANCHES" | grep -q "^$ENV$"; then
112
- echo "Deleting stale environment: $ENV"
113
- npx zuplo delete --environment "$ENV" --api-key "$ZUPLO_API_KEY" --wait || true
114
- fi
115
- done
103
+ # Get all remote branches, converted to the deployment-name branch
104
+ # segment format: lowercase, special characters replaced by hyphens,
105
+ # truncated to 10 characters
106
+ BRANCHES=$(git branch -r | sed 's|origin/||' | tr -d ' ' |
107
+ tr '/_' '--' | tr '[:upper:]' '[:lower:]' |
108
+ cut -c1-10 | sed 's/-*$//')
109
+
110
+ # List deployed environments as JSON. Each entry has the shape
111
+ # {"projectName": "...", "name": "...", "url": "..."}
112
+ npx zuplo list --api-key "$ZUPLO_API_KEY" \
113
+ --output json --show-details > environments.json
114
+
115
+ # Deployment names follow the format {project}-{branch}-{hash}
116
+ jq -r '.[] | "\(.name) \(.url)"' environments.json |
117
+ while read -r NAME URL; do
118
+ # Skip protected environments
119
+ case "$NAME" in
120
+ *-main-* | *-production-* | *-staging-*) continue ;;
121
+ esac
122
+
123
+ # Delete only if no branch matches the deployment name
124
+ STALE=true
125
+ for BRANCH in $BRANCHES; do
126
+ if [[ "$NAME" == *"-$BRANCH-"* ]]; then
127
+ STALE=false
128
+ break
129
+ fi
130
+ done
131
+
132
+ if [[ "$STALE" == "true" ]]; then
133
+ echo "Deleting stale environment: $NAME"
134
+ npx zuplo delete --url "$URL" --api-key "$ZUPLO_API_KEY" --wait || true
135
+ fi
136
+ done
116
137
  ```
117
138
 
118
139
  ## Next Steps
@@ -34,9 +34,14 @@ jobs:
34
34
  - name: Deploy to Zuplo
35
35
  id: deploy
36
36
  shell: bash
37
+ env:
38
+ # head_ref is the source branch on pull_request events (where the
39
+ # checkout is the pull/<number>/merge ref, not the branch);
40
+ # ref_name covers push events
41
+ ENVIRONMENT: ${{ github.head_ref || github.ref_name }}
37
42
  run: |
38
43
  # Capture deployment output
39
- OUTPUT=$(npx zuplo deploy --api-key "$ZUPLO_API_KEY" 2>&1)
44
+ OUTPUT=$(npx zuplo deploy --api-key "$ZUPLO_API_KEY" --environment "$ENVIRONMENT" 2>&1)
40
45
  echo "$OUTPUT"
41
46
 
42
47
  # Extract the deployment URL
@@ -53,6 +58,14 @@ This workflow:
53
58
  2. Runs your test suite against the live deployment
54
59
  3. Fails the workflow if any tests fail
55
60
 
61
+ The deploy step passes `--environment` explicitly because this workflow runs on
62
+ both `push` and `pull_request` events. The expression
63
+ `${{ github.head_ref || github.ref_name }}` resolves to the branch name on
64
+ either trigger, so every run for a branch updates the same environment. Without
65
+ it, `pull_request` runs create a second environment named after the PR merge ref
66
+ instead of your branch — see
67
+ [PR Preview Environments](./pr-preview-environments.mdx) for details.
68
+
56
69
  ## Writing Tests
57
70
 
58
71
  Place test files in the `tests` folder with the `.test.ts` extension: