zuplo 6.70.71 → 6.71.0

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 (43) hide show
  1. package/docs/analytics/access-and-entitlements.md +1 -1
  2. package/docs/analytics/overview.md +12 -8
  3. package/docs/analytics/reference/metrics-glossary.md +3 -3
  4. package/docs/analytics/shared-controls.md +12 -11
  5. package/docs/analytics/tabs/agents.md +14 -14
  6. package/docs/analytics/tabs/consumers.md +6 -6
  7. package/docs/analytics/tabs/graphql.md +5 -4
  8. package/docs/analytics/tabs/mcp.md +7 -7
  9. package/docs/analytics/tabs/origins.md +11 -10
  10. package/docs/analytics/tabs/requests.md +6 -5
  11. package/docs/articles/accounts/enterprise-sso.mdx +8 -6
  12. package/docs/articles/api-key-administration.mdx +4 -0
  13. package/docs/articles/bypass-policy-for-testing.mdx +4 -0
  14. package/docs/articles/environment-variables.mdx +5 -1
  15. package/docs/articles/environments.mdx +2 -2
  16. package/docs/articles/graphql.mdx +23 -39
  17. package/docs/articles/mcp-quickstart-local.mdx +2 -1
  18. package/docs/articles/mcp-quickstart.mdx +6 -1
  19. package/docs/articles/multiple-auth-policies.mdx +2 -2
  20. package/docs/articles/openapi.mdx +6 -1
  21. package/docs/articles/rename-or-move-project.mdx +4 -0
  22. package/docs/articles/securing-your-backend.mdx +11 -3
  23. package/docs/articles/source-control-setup-github.mdx +4 -0
  24. package/docs/articles/troubleshooting-slow-responses.mdx +2 -2
  25. package/docs/articles/troubleshooting.md +3 -3
  26. package/docs/dedicated/akamai/architecture.mdx +9 -9
  27. package/docs/dev-portal/zudoku/components/browser-window.mdx +94 -0
  28. package/docs/dev-portal/zudoku/components/landing-page.mdx +283 -0
  29. package/docs/handlers/system-handlers.mdx +2 -1
  30. package/docs/mcp-gateway/how-to/connect-upstream-api-key.mdx +2 -2
  31. package/docs/mcp-gateway/observability/analytics.mdx +17 -13
  32. package/docs/mcp-gateway/quickstart.mdx +4 -3
  33. package/docs/mcp-gateway/troubleshooting.mdx +4 -4
  34. package/docs/policies/_index.md +1 -0
  35. package/docs/policies/data-loss-prevention-inbound/doc.md +23 -24
  36. package/docs/policies/data-loss-prevention-inbound/intro.md +9 -9
  37. package/docs/policies/data-loss-prevention-outbound/doc.md +25 -26
  38. package/docs/policies/data-loss-prevention-outbound/intro.md +10 -10
  39. package/docs/policies/graphql-analytics-outbound/doc.md +93 -0
  40. package/docs/policies/graphql-analytics-outbound/intro.md +12 -0
  41. package/docs/policies/graphql-analytics-outbound/schema.json +93 -0
  42. package/docs/programmable-api/zuplo-context.mdx +3 -2
  43. package/package.json +4 -4
@@ -29,8 +29,12 @@ Open the **Settings** section of your project and select **Environment
29
29
  Variables**. Create a new variable and name it `BACKEND_SECRET`. Set the value
30
30
  to a secure, random value. Ensure that the value is marked as a secret.
31
31
 
32
+ <ModalScreenshot>
33
+
32
34
  ![Set Environment Variable](../../public/media/securing-backend-shared-secret/image.png)
33
35
 
36
+ </ModalScreenshot>
37
+
34
38
  ### Step 2: Create a set header policy
35
39
 
36
40
  Create a policy that sets the `BACKEND_SECRET` as a header on the request to
@@ -40,8 +44,12 @@ is sent to your backend.
40
44
  Navigate to the route you want to secure and add a new policy. Select the **Add
41
45
  or Set Request Headers** policy type and configure it as follows:
42
46
 
47
+ <ModalScreenshot>
48
+
43
49
  ![Set Header Policy](../../public/media/securing-backend-shared-secret/image-1.png)
44
50
 
51
+ </ModalScreenshot>
52
+
45
53
  The configuration uses the environment variable via the `$env(BACKEND_SECRET)`
46
54
  selector as shown below.
47
55
 
@@ -98,10 +106,10 @@ interested in using this option please contact us at `support@zuplo.com`.
98
106
  Utilize the IAM controls provided by your Cloud host to secure inbound requests
99
107
  and allow only authorized service principals access to your service.
100
108
 
101
- - For Azure users, you can user our
109
+ - For Azure users, you can use the
102
110
  [Upstream Azure AD Service Auth](../policies/upstream-azure-ad-service-auth-inbound.mdx)
103
- policy. This uses Azure AD App registrations to create a token that Zuplo will
104
- send to requests to Azure.
111
+ policy. This uses Microsoft Entra ID (formerly Azure AD) App registrations to
112
+ create a token that Zuplo sends with requests to Azure.
105
113
 
106
114
  - For GCP users, you can use our
107
115
  [Upstream GCP Service AUth](../policies/upstream-gcp-service-auth-inbound.mdx)
@@ -130,8 +130,12 @@ If you have an existing GitHub repository that contains a Zuplo project, you can
130
130
  connect to that repository when you create a new project. Select **Import
131
131
  existing project** then select your GitHub organization and repository.
132
132
 
133
+ <ModalScreenshot>
134
+
133
135
  ![Import existing project to Zuplo](../../public/media/source-control/image-1.png)
134
136
 
137
+ </ModalScreenshot>
138
+
135
139
  ## What's Included
136
140
 
137
141
  With GitHub connected, you get:
@@ -226,8 +226,8 @@ period of inactivity is slow. Subsequent requests are fast.
226
226
 
227
227
  ### Analytics Dashboard
228
228
 
229
- Zuplo's analytics dashboard provides at-a-glance visibility into your API's
230
- performance. Use it to:
229
+ Zuplo's analytics dashboard, in the **Observability** tab of your project,
230
+ provides at-a-glance visibility into your API's performance. Use it to:
231
231
 
232
232
  - Identify slow endpoints by reviewing request latency data
233
233
  - Filter by route, API key, or time period to isolate patterns
@@ -177,9 +177,9 @@ const response = await fetch("https://api.example.com/data", {
177
177
  ### Portal live logs
178
178
 
179
179
  The Zuplo Portal provides real-time log viewing for deployed environments. Open
180
- the [**Environments**](https://portal.zuplo.com/+/account/project/environments)
181
- tab in your project, select the deployed environment, and open the logs tab to
182
- see live request logs and any messages logged with `context.log`.
180
+ the **Observability** tab in your project — the **Logs** view opens by default —
181
+ then use the **Environment** filter to select the deployed environment and see
182
+ live request logs and any messages logged with `context.log`.
183
183
 
184
184
  ### Using context.log
185
185
 
@@ -229,7 +229,7 @@ Zuplo and your backend services. For complete documentation, see
229
229
  | **Shared Secret / API Key** | Add a secret header to requests that only the gateway knows. Simple to implement and widely used by companies like Stripe and Supabase. |
230
230
  | **Zuplo JWT Service** | Issue signed JWTs that your backend validates using Zuplo's JWKS endpoint. Provides cryptographic proof that requests originate from your gateway. |
231
231
  | **mTLS (Mutual TLS)** | Certificate-based authentication where both gateway and backend present certificates. Provides zero-trust security for enterprise requirements. |
232
- | **Cloud Provider IAM** | Use AWS IAM, GCP Identity-Aware Proxy, or Azure AD to authorize requests. No credentials to manage - uses federated identity. |
232
+ | **Cloud Provider IAM** | Use AWS IAM, GCP Identity-Aware Proxy, or Microsoft Entra ID to authorize requests. No credentials to manage - uses federated identity. |
233
233
  | **Secure Tunnel (VPN)** | WireGuard-based tunnel for backends that can't be exposed to the internet. Useful for on-premise or bare-metal deployments. |
234
234
  | **Private Network** | VPC peering, PrivateLink, or Transit Gateway for private connectivity without traversing the public internet. |
235
235
 
@@ -238,14 +238,14 @@ Zuplo and your backend services. For complete documentation, see
238
238
  While most authentication methods work anywhere, some approaches are better
239
239
  suited for specific scenarios:
240
240
 
241
- | Backend Location | Recommended Methods | Notes |
242
- | ---------------------------- | ------------------------------------------------- | --------------------------------------------------------------------------- |
243
- | **Akamai Connected Cloud** | Shared secret, Zuplo JWT, mTLS | All methods work well; choose based on your security requirements |
244
- | **AWS** | AWS IAM (federated identity), mTLS, shared secret | IAM provides credential-free auth; works with Lambda, API Gateway, ECS, EKS |
245
- | **GCP** | GCP Identity-Aware Proxy, GCP Service Auth, mTLS | IAP provides zero-trust access to Cloud Run, GKE, and Compute Engine |
246
- | **Azure** | Azure AD Service Auth, mTLS, shared secret | Azure AD integrates with App Service, Functions, and AKS |
247
- | **On-Premise / Data Center** | Secure tunnel, mTLS, shared secret | Tunnel allows private connectivity; mTLS provides strong authentication |
248
- | **Third-Party APIs** | Shared secret, API keys, mTLS | Use whatever the third-party API supports |
241
+ | Backend Location | Recommended Methods | Notes |
242
+ | ---------------------------- | ---------------------------------------------------- | --------------------------------------------------------------------------- |
243
+ | **Akamai Connected Cloud** | Shared secret, Zuplo JWT, mTLS | All methods work well; choose based on your security requirements |
244
+ | **AWS** | AWS IAM (federated identity), mTLS, shared secret | IAM provides credential-free auth; works with Lambda, API Gateway, ECS, EKS |
245
+ | **GCP** | GCP Identity-Aware Proxy, GCP Service Auth, mTLS | IAP provides zero-trust access to Cloud Run, GKE, and Compute Engine |
246
+ | **Azure** | Microsoft Entra ID Service Auth, mTLS, shared secret | Microsoft Entra ID integrates with App Service, Functions, and AKS |
247
+ | **On-Premise / Data Center** | Secure tunnel, mTLS, shared secret | Tunnel allows private connectivity; mTLS provides strong authentication |
248
+ | **Third-Party APIs** | Shared secret, API keys, mTLS | Use whatever the third-party API supports |
249
249
 
250
250
  ### Choosing an authentication method
251
251
 
@@ -0,0 +1,94 @@
1
+ ---
2
+ title: Browser Window
3
+ sidebar_icon: app-window
4
+ ---
5
+
6
+ import { BrowserWindow } from "zudoku/components";
7
+ import { Button } from "zudoku/ui/Button";
8
+
9
+ A mock browser window for presenting UI previews, screenshots-as-code, or full page layouts in your
10
+ documentation. It renders its children inside a browser-style frame with a URL bar and an optional
11
+ zoom control — the current scale is displayed like in a real browser and readers can zoom in and out
12
+ themselves.
13
+
14
+ ## Import
15
+
16
+ ```tsx
17
+ import { BrowserWindow } from "zudoku/components";
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ <BrowserWindow>
23
+ <div className="flex flex-col items-center gap-3 p-10 text-center">
24
+ <span className="text-2xl font-bold">Hello, world!</span>
25
+ <p className="text-muted-foreground">Any content renders inside the browser frame.</p>
26
+ <Button>Get started</Button>
27
+ </div>
28
+ </BrowserWindow>
29
+
30
+ ```tsx
31
+ <BrowserWindow>
32
+ <div className="flex flex-col items-center gap-3 p-10 text-center">
33
+ <span className="text-2xl font-bold">Hello, world!</span>
34
+ <p className="text-muted-foreground">Any content renders inside the browser frame.</p>
35
+ <Button>Get started</Button>
36
+ </div>
37
+ </BrowserWindow>
38
+ ```
39
+
40
+ ## Scale
41
+
42
+ Use the `scale` prop to set the initial zoom of the content. This is useful for presenting
43
+ full-width layouts, like a landing page, at a reduced size. Passing a `scale` enables the zoom
44
+ control in the toolbar showing the current scale — readers can change it with the `+`/`-` buttons or
45
+ click the percentage to reset it, just like in a real browser. Without a `scale`, the zoom control
46
+ is hidden and the content renders at full size (pass `scale={1}` to start at 100% with the control
47
+ enabled).
48
+
49
+ <BrowserWindow scale={0.5}>
50
+ <div className="flex flex-col items-center gap-3 p-10 text-center">
51
+ <span className="text-4xl font-bold">Scaled to 50%</span>
52
+ <p className="text-muted-foreground">
53
+ The content is laid out at full width and scaled down to fit.
54
+ </p>
55
+ </div>
56
+ </BrowserWindow>
57
+
58
+ ```tsx
59
+ <BrowserWindow scale={0.5}>
60
+ <div className="flex flex-col items-center gap-3 p-10 text-center">
61
+ <span className="text-4xl font-bold">Scaled to 50%</span>
62
+ <p className="text-muted-foreground">
63
+ The content is laid out at full width and scaled down to fit.
64
+ </p>
65
+ </div>
66
+ </BrowserWindow>
67
+ ```
68
+
69
+ Scaling affects layout, not just size: at `scale={0.5}` the content is laid out at twice the
70
+ container width and scaled down, so responsive layouts behave as if viewed on a larger screen.
71
+
72
+ ## URL
73
+
74
+ Set the `url` prop to change the address shown in the URL bar (defaults to `localhost:3000`):
75
+
76
+ <BrowserWindow url="https://developers.example.com">
77
+ <p className="p-10 text-center text-muted-foreground">Your developer portal</p>
78
+ </BrowserWindow>
79
+
80
+ ```tsx
81
+ <BrowserWindow url="https://developers.example.com">
82
+ <p className="p-10 text-center text-muted-foreground">Your developer portal</p>
83
+ </BrowserWindow>
84
+ ```
85
+
86
+ ## Props
87
+
88
+ | Prop | Type | Description |
89
+ | ------------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
90
+ | `url` | `string` | Address displayed in the URL bar. Defaults to `localhost:3000`. |
91
+ | `scale` | `number` | Initial zoom of the content (e.g. `0.75` for 75%). Enables the zoom control; if omitted, the control is hidden and content renders at full size. |
92
+ | `className` | `string` | Additional classes for the outer frame. |
93
+ | `contentClassName` | `string` | Additional classes for the content viewport. |
94
+ | `children` | `ReactNode` | The content rendered inside the browser window. |
@@ -0,0 +1,283 @@
1
+ ---
2
+ title: Landing Page
3
+ sidebar_icon: layout-template
4
+ ---
5
+
6
+ import { BrowserWindow, LandingPage } from "zudoku/components";
7
+ import { BookOpenIcon, CodeIcon, KeyIcon, RocketIcon, WebhookIcon, ZapIcon } from "zudoku/icons";
8
+
9
+ A ready-made, customizable landing page for your developer portal. It comes in three variants
10
+ covering the most common layouts: a centered hero, a two-column split hero, and a compact
11
+ documentation hub.
12
+
13
+ Use it as the `element` of a [custom page](/dev-portal/zudoku/custom-pages) — typically your home page:
14
+
15
+ ```tsx title=zudoku.config.tsx
16
+ import { LandingPage } from "zudoku/components";
17
+
18
+ const config = {
19
+ navigation: [
20
+ {
21
+ type: "custom-page",
22
+ path: "/",
23
+ element: (
24
+ <LandingPage
25
+ title="Build with our API"
26
+ description="Everything you need to integrate in minutes."
27
+ actions={[
28
+ { label: "Get started", href: "/getting-started" },
29
+ { label: "API Reference", href: "/api" },
30
+ ]}
31
+ />
32
+ ),
33
+ },
34
+ // ...
35
+ ],
36
+ };
37
+ ```
38
+
39
+ ## Import
40
+
41
+ ```tsx
42
+ import { LandingPage } from "zudoku/components";
43
+ ```
44
+
45
+ ## Variants
46
+
47
+ ### Hero (default)
48
+
49
+ A centered hero with call-to-action buttons and an optional feature grid below. The classic landing
50
+ page for product-focused portals. The previews on this page are presented in a
51
+ [Browser Window](./browser-window) component.
52
+
53
+ <BrowserWindow url="https://developers.example.com" scale={0.75} contentClassName="px-8">
54
+ <LandingPage
55
+ eyebrow="Developer Platform"
56
+ title="Build with our API"
57
+ description="Everything you need to integrate payments, webhooks, and more — in minutes, not days."
58
+ actions={[
59
+ { label: "Get started", href: "/docs/getting-started" },
60
+ { label: "API Reference", href: "/docs", variant: "outline" },
61
+ ]}
62
+ features={[
63
+ {
64
+ icon: <ZapIcon />,
65
+ title: "Fast integration",
66
+ description: "Go from zero to your first API call in under five minutes.",
67
+ },
68
+ {
69
+ icon: <KeyIcon />,
70
+ title: "API keys built in",
71
+ description: "Issue, rotate, and revoke keys right from the portal.",
72
+ },
73
+ {
74
+ icon: <WebhookIcon />,
75
+ title: "Webhooks",
76
+ description: "Subscribe to events and react to changes in real time.",
77
+ },
78
+ ]}
79
+ />
80
+ </BrowserWindow>
81
+
82
+ ```tsx
83
+ <LandingPage
84
+ eyebrow="Developer Platform"
85
+ title="Build with our API"
86
+ description="Everything you need to integrate payments, webhooks, and more — in minutes, not days."
87
+ actions={[
88
+ { label: "Get started", href: "/getting-started" },
89
+ { label: "API Reference", href: "/api", variant: "outline" },
90
+ ]}
91
+ features={[
92
+ {
93
+ icon: <ZapIcon />,
94
+ title: "Fast integration",
95
+ description: "Go from zero to your first API call in under five minutes.",
96
+ },
97
+ {
98
+ icon: <KeyIcon />,
99
+ title: "API keys built in",
100
+ description: "Issue, rotate, and revoke keys right from the portal.",
101
+ },
102
+ {
103
+ icon: <WebhookIcon />,
104
+ title: "Webhooks",
105
+ description: "Subscribe to events and react to changes in real time.",
106
+ },
107
+ ]}
108
+ />
109
+ ```
110
+
111
+ ### Split
112
+
113
+ A two-column hero with your own content on the side — an illustration, screenshot, or code sample
114
+ passed via the `aside` prop. A great fit for developer-oriented portals that want to show code up
115
+ front.
116
+
117
+ <BrowserWindow url="https://shipping.example.com" scale={0.75} contentClassName="px-8">
118
+ <LandingPage
119
+ variant="split"
120
+ eyebrow="Shipping API"
121
+ title="Ship anywhere in the whole universe"
122
+ description="Create and manage shipments, track packages in real-time, and integrate with multiple carriers through a single interface."
123
+ actions={[
124
+ { label: "Get started", href: "/docs/getting-started" },
125
+ { label: "View on GitHub", href: "https://github.com/zuplo/zudoku", variant: "outline" },
126
+ ]}
127
+ aside={
128
+ <div className="rounded-xl border bg-card p-4 font-mono text-sm">
129
+ <pre>{`curl https://api.example.com/v1/shipments \\
130
+ -H "Authorization: Bearer $API_KEY" \\
131
+ -d destination="alpha-centauri"`}</pre>
132
+ </div>
133
+ }
134
+ />
135
+ </BrowserWindow>
136
+
137
+ ```tsx
138
+ <LandingPage
139
+ variant="split"
140
+ eyebrow="Shipping API"
141
+ title="Ship anywhere in the whole universe"
142
+ description="Create and manage shipments, track packages in real-time, and integrate with multiple carriers through a single interface."
143
+ actions={[
144
+ { label: "Get started", href: "/getting-started" },
145
+ {
146
+ label: "View on GitHub",
147
+ href: "https://github.com/zuplo/zudoku",
148
+ variant: "outline",
149
+ },
150
+ ]}
151
+ aside={
152
+ <div className="rounded-xl border bg-card p-4 font-mono text-sm">
153
+ <pre>{`curl https://api.example.com/v1/shipments \\
154
+ -H "Authorization: Bearer $API_KEY" \\
155
+ -d destination="alpha-centauri"`}</pre>
156
+ </div>
157
+ }
158
+ />
159
+ ```
160
+
161
+ The `aside` accepts any React node — use an `<img />` for an illustration instead of code:
162
+
163
+ ```tsx
164
+ <LandingPage
165
+ variant="split"
166
+ title="Ship anywhere"
167
+ aside={<img src="/hero.webp" alt="Hero" className="rounded-3xl" />}
168
+ />
169
+ ```
170
+
171
+ ### Grid
172
+
173
+ A compact header followed by prominent, clickable feature cards. Ideal as a documentation hub that
174
+ routes visitors to the right section quickly.
175
+
176
+ <BrowserWindow url="https://developers.example.com/docs" scale={0.75} contentClassName="px-8">
177
+ <LandingPage
178
+ variant="grid"
179
+ title="Documentation"
180
+ description="Explore guides, API references, and examples to get the most out of the platform."
181
+ features={[
182
+ {
183
+ icon: <RocketIcon />,
184
+ title: "Getting Started",
185
+ description: "Set up your account and make your first request.",
186
+ href: "/docs/getting-started",
187
+ },
188
+ {
189
+ icon: <BookOpenIcon />,
190
+ title: "Guides",
191
+ description: "Step-by-step tutorials for common use cases.",
192
+ href: "/docs",
193
+ },
194
+ {
195
+ icon: <CodeIcon />,
196
+ title: "API Reference",
197
+ description: "Complete reference for every endpoint and type.",
198
+ href: "/docs",
199
+ },
200
+ {
201
+ icon: <WebhookIcon />,
202
+ title: "Webhooks",
203
+ description: "Listen to events and build real-time integrations.",
204
+ href: "/docs",
205
+ },
206
+ ]}
207
+ />
208
+ </BrowserWindow>
209
+
210
+ ```tsx
211
+ <LandingPage
212
+ variant="grid"
213
+ title="Documentation"
214
+ description="Explore guides, API references, and examples to get the most out of the platform."
215
+ features={[
216
+ {
217
+ icon: <RocketIcon />,
218
+ title: "Getting Started",
219
+ description: "Set up your account and make your first request.",
220
+ href: "/getting-started",
221
+ },
222
+ {
223
+ icon: <BookOpenIcon />,
224
+ title: "Guides",
225
+ description: "Step-by-step tutorials for common use cases.",
226
+ href: "/guides",
227
+ },
228
+ {
229
+ icon: <CodeIcon />,
230
+ title: "API Reference",
231
+ description: "Complete reference for every endpoint and type.",
232
+ href: "/api",
233
+ },
234
+ {
235
+ icon: <WebhookIcon />,
236
+ title: "Webhooks",
237
+ description: "Listen to events and build real-time integrations.",
238
+ href: "/webhooks",
239
+ },
240
+ ]}
241
+ />
242
+ ```
243
+
244
+ ## Props
245
+
246
+ | Prop | Type | Description |
247
+ | ------------- | ----------------------------- | ------------------------------------------------------------------------------------------------ |
248
+ | `variant` | `"hero" \| "split" \| "grid"` | Layout variant. Defaults to `"hero"`. |
249
+ | `title` | `ReactNode` | Main headline. Required. |
250
+ | `eyebrow` | `ReactNode` | Short label displayed above the title. |
251
+ | `description` | `ReactNode` | Supporting text below the title. |
252
+ | `actions` | `LandingPageAction[]` | Call-to-action buttons. Each action has `label`, `href`, and an optional Button `variant`. |
253
+ | `features` | `LandingPageFeature[]` | Feature cards with optional `icon`, `title`, `description`, and `href` (making the card a link). |
254
+ | `aside` | `ReactNode` | Side content for the `split` variant (image, code sample, …). |
255
+ | `children` | `ReactNode` | Additional content rendered below the built-in sections. |
256
+ | `className` | `string` | Additional classes for the outer `<section>`. |
257
+
258
+ ### Links
259
+
260
+ `href` values in `actions` and `features` are rendered as client-side router links for internal
261
+ paths (e.g. `/getting-started`) and as regular links opening in a new tab for external URLs (e.g.
262
+ `https://github.com/...`).
263
+
264
+ ## Customization
265
+
266
+ - **Buttons**: The first action defaults to the primary button style, all following actions to
267
+ `outline`. Override per action with `variant` (any [Button](/dev-portal/zudoku/components/button) variant).
268
+ - **Rich titles**: `title`, `description`, and `eyebrow` accept any React node, so you can use
269
+ custom markup like highlighted words:
270
+ `title={<>Ship <span className="text-primary">faster</span></>}`.
271
+ - **Extra sections**: Pass `children` to append your own sections (testimonials, pricing, …) below
272
+ the built-in layout.
273
+ - **Page metadata**: Combine with the [Head](/dev-portal/zudoku/components/head) component to set the page title:
274
+
275
+ ```tsx
276
+ import { Head, LandingPage } from "zudoku/components";
277
+
278
+ <LandingPage title="Build with our API">
279
+ <Head>
280
+ <title>Home</title>
281
+ </Head>
282
+ </LandingPage>;
283
+ ```
@@ -5,7 +5,8 @@ sidebar_label: Internal Route Handlers
5
5
 
6
6
  The Zuplo Runtime automatically registers certain routes on your gateway to
7
7
  provide enhanced functionality. Requests to these routes may appear in your
8
- Analytics page. Below is a list of reserved routes:
8
+ project's analytics under the **Observability** tab. Below is a list of reserved
9
+ routes:
9
10
 
10
11
  | Name | Method | Path | Description |
11
12
  | ----------------------- | ------- | --------------------------------- | ----------------------------------------------------------- |
@@ -48,7 +48,7 @@ Virtual Server**, with these choices:
48
48
 
49
49
  <ModalScreenshot size="md">
50
50
 
51
- ![Outbound auth set to None with Remove auth token selected](../../public/media/mcp-gateway-upstream-api-key/01-outbound-auth-none.png)
51
+ ![Outbound auth set to None with Remove auth token selected](../../../public/media/mcp-gateway-upstream-api-key/01-outbound-auth-none.png)
52
52
 
53
53
  </ModalScreenshot>
54
54
 
@@ -85,7 +85,7 @@ set.
85
85
 
86
86
  <ModalScreenshot size="md">
87
87
 
88
- ![The set-headers-inbound policy added to the end of the request policy stack](../../public/media/mcp-gateway-upstream-api-key/02-policy-stack.png)
88
+ ![The set-headers-inbound policy added to the end of the request policy stack](../../../public/media/mcp-gateway-upstream-api-key/02-policy-stack.png)
89
89
 
90
90
  </ModalScreenshot>
91
91
 
@@ -7,10 +7,11 @@ description:
7
7
  ---
8
8
 
9
9
  Every authenticated MCP request the Zuplo MCP Gateway handles produces a set of
10
- structured analytics events. The events power the MCP tab on the Zuplo Portal's
11
- **Analytics** page and feed the same data into Zuplo's standard log and metrics
12
- pipelines. This page explains why each event exists, the dimensions that scope
13
- the data, and the operational questions the dashboard exists to answer.
10
+ structured analytics events. The events power the MCP section of the Zuplo
11
+ Portal's **Observability → Analytics** view and feed the same data into Zuplo's
12
+ standard log and metrics pipelines. This page explains why each event exists,
13
+ the dimensions that scope the data, and the operational questions the dashboard
14
+ exists to answer.
14
15
 
15
16
  ## What the analytics are for
16
17
 
@@ -125,15 +126,18 @@ A few panels carry detail worth calling out:
125
126
 
126
127
  ## Where to find it
127
128
 
128
- The MCP analytics dashboard is a tab on the Zuplo Portal's **Analytics** page.
129
- At the account scope,
130
- [Analytics → MCP](https://portal.zuplo.com/+/account/analytics) aggregates
131
- across every project on the account that has MCP routes. At the project scope,
132
- [Analytics MCP](https://portal.zuplo.com/+/account/project/analytics) shows
133
- that project's events only.
134
-
135
- The MCP tab appears automatically once any MCP request has been recorded for the
136
- project. New projects show the empty state until the first MCP request lands.
129
+ The MCP analytics dashboard is a section of the Analytics view inside the Zuplo
130
+ Portal's **Observability** tab. At the account scope,
131
+ [**Observability → Analytics → MCP**](https://portal.zuplo.com/+/account/observability/analytics/mcp)
132
+ aggregates across every project on the account that has MCP routes. At the
133
+ project scope, open your project, click **Observability**, then select
134
+ **Analytics MCP** to see
135
+ [that project's events](https://portal.zuplo.com/+/account/project/analytics)
136
+ only.
137
+
138
+ The MCP section appears automatically once any MCP request has been recorded for
139
+ the project. New projects show the empty state until the first MCP request
140
+ lands.
137
141
 
138
142
  ## Reference: event types
139
143
 
@@ -251,9 +251,10 @@ result on your machine.
251
251
  tool, then returns results proxied through the gateway.
252
252
 
253
253
  Open the project's
254
- [Analytics dashboard](https://portal.zuplo.com/+/account/project/analytics)
255
- and switch to the **MCP** tab to see the call appear in the events timeline,
256
- the success rate, the top capabilities table, and the user breakdown.
254
+ [**Observability → Analytics**](https://portal.zuplo.com/+/account/project/analytics)
255
+ view and select the **MCP** section to see the call appear in the events
256
+ timeline, the success rate, the top capabilities table, and the user
257
+ breakdown.
257
258
 
258
259
  </Stepper>
259
260
 
@@ -216,10 +216,10 @@ window where a stolen cookie is useful.
216
216
 
217
217
  ## Where to look when none of the above match
218
218
 
219
- - Open the project's **Logs** in the Portal and filter on the request's
220
- `zuplo-request-id`. Gateway log entries include the relevant `operationId` and
221
- `subjectId`.
222
- - Open the **Analytics** dashboard and switch to the **MCP** tab. The "Top
219
+ - Open the project's **Observability → Logs** view in the Portal and filter on
220
+ the request's `zuplo-request-id`. Gateway log entries include the relevant
221
+ `operationId` and `subjectId`.
222
+ - Open **Observability Analytics** and select the **MCP** section. The "Top
223
223
  Reason Codes" and "Failure Origins" panels surface the highest-cardinality
224
224
  failure modes for the current time window.
225
225
  - For OAuth-specific issues, the
@@ -43,6 +43,7 @@
43
43
  | formdata-to-json-inbound | Form Data to JSON | Converts form data in the incoming request to JSON. | api-gateway |
44
44
  | galileo-tracing-inbound | Galileo Tracing | Galileo Tracing Inbound Policy | ai-gateway |
45
45
  | geo-filter-inbound | Geo-location filtering | Block requests based on geo-location parameters: country, region code, and ASN | api-gateway |
46
+ | graphql-analytics-outbound | GraphQL Analytics | Reports GraphQL errors returned in response bodies to Zuplo's GraphQL analytics. GraphQL servers following the standard Apollo / graphql-yoga pattern return `200 OK` with an `errors[]` array in the body when an operation fails, which HTTP-level analytics alone report as a success — add this policy to a GraphQL route and failed operations show up as failures on the GraphQL dashboard, classified by error type. Each error in `errors[]` is classified from its `extensions.code` following the Apollo Server conventions (`GRAPHQL_PARSE_FAILED` → `syntax`, `GRAPHQL_VALIDATION_FAILED` → `validation`, `UNAUTHENTICATED` / `FORBIDDEN` → `auth`, timeout codes → `timeout`); custom codes can be mapped with `errorCodeClassification`, and anything unrecognized falls back to `defaultErrorClass` (`resolver`). Optionally set `logErrors` to also write a structured warning per errored response. Bodies larger than `maxResponseBytes` (default 5 MiB) are not inspected. The response always passes through unchanged — the body is read from a clone, and any internal failure is swallowed so reporting can never break the request. The route must be marked `x-graphql: true` in `routes.oas.json` (which enables GraphQL analytics for the route); without the marker the policy logs a warning and does nothing. | api-gateway |
46
47
  | graphql-complexity-limit-inbound | GraphQL Complexity Limit | Policy that limits the complexity and depth of GraphQL queries to prevent abuse. Protects your GraphQL API from expensive queries that could cause performance issues or denial of service attacks. | api-gateway |
47
48
  | graphql-disable-introspection-inbound | GraphQL Disable Introspection | Policy that disables GraphQL introspection queries in production. Introspection allows clients to discover the schema, which can be a security risk as it exposes your entire API structure. | api-gateway |
48
49
  | graphql-introspection-filter-outbound | GraphQL Introspection Filter | Filters GraphQL introspection responses to exclude specific types and fields. This policy intercepts GraphQL introspection query responses and removes configured types and fields from the schema. Useful for hiding internal types or sensitive fields from the public schema. | api-gateway |