zuplo 7.9.6 → 7.9.9

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.
@@ -399,6 +399,8 @@ different levels of your API documentation.
399
399
  ### Operations
400
400
 
401
401
  - `x-zudoku-playground-enabled`: Control playground visibility for an operation (default: `true`)
402
+ - `x-internal`: Hide an operation from the documentation. Also works on path items and parameters.
403
+ See [`x-internal`](../openapi-extensions/x-internal)
402
404
  - `x-explorer-enabled`: Alias for `x-zudoku-playground-enabled` for compatibility Example:
403
405
 
404
406
  ```json
@@ -28,11 +28,12 @@ Add the `authentication` property to your [Dev Portal configuration](./overview.
28
28
  }
29
29
  ```
30
30
 
31
- | Option | Required | Description |
32
- | ---------- | -------- | -------------------------------------------------------------------------------------------- |
33
- | `clientId` | Yes | The OAuth client ID issued by your provider. |
34
- | `issuer` | Yes | The issuer URL. Dev Portal discovers endpoints from `<issuer>/.well-known/openid-configuration`. |
35
- | `scopes` | No | Scopes to request. Defaults to `["openid", "profile", "email"]`. |
31
+ | Option | Required | Description |
32
+ | ----------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
33
+ | `clientId` | Yes | The OAuth client ID issued by your provider. |
34
+ | `issuer` | Yes | The issuer URL. Dev Portal discovers endpoints from `<issuer>/.well-known/openid-configuration`. |
35
+ | `scopes` | No | Scopes to request. Defaults to `["openid", "profile", "email"]`. |
36
+ | `allowInsecureRequests` | No | Allow discovery and token requests against an `http://` issuer. Defaults to `false`. Intended only for local development — never enable this in production. |
36
37
 
37
38
  ## Provider Setup
38
39
 
@@ -126,6 +127,27 @@ After sign-in Dev Portal calls the provider's
126
127
  `name`, `email`, `picture`, and `email_verified` from the response. Map these claims in your
127
128
  provider if they are not emitted by default.
128
129
 
130
+ ## Local Development with an HTTP Issuer
131
+
132
+ `oauth4webapi` (the library Dev Portal uses under the hood) rejects issuers that don't use `https://` by
133
+ default, since OIDC requires TLS in production. If you're running an identity provider locally over
134
+ plain HTTP (e.g. a dockerized Keycloak on `http://localhost:9090`), set `allowInsecureRequests` to
135
+ `true` so discovery and token requests are allowed to use `http://`:
136
+
137
+ ```typescript title="zudoku.config.ts"
138
+ {
139
+ authentication: {
140
+ type: "openid",
141
+ clientId: "<your-client-id>",
142
+ issuer: "http://localhost:9090/auth/realms/<your-realm>",
143
+ allowInsecureRequests: true,
144
+ },
145
+ }
146
+ ```
147
+
148
+ Only enable this for local development. Never set `allowInsecureRequests` to `true` against a
149
+ production issuer.
150
+
129
151
  ## Troubleshooting
130
152
 
131
153
  - **Discovery fails**: verify `<issuer>/.well-known/openid-configuration` resolves and matches the
@@ -214,6 +214,31 @@ fields are used to display the user profile:
214
214
 
215
215
  If the provider does not return a field, it will be left blank.
216
216
 
217
+ ## Redirects after sign-in
218
+
219
+ By default, users return to the page they started from after signing in. For
220
+ [protected routes](./protected-routes.md) that is the path and query string they tried to open; for
221
+ `useAuth().login({ redirectTo })` it is the `redirectTo` you pass.
222
+
223
+ Setting `redirectToAfterSignIn` overrides that return URL: every sign-in lands on the configured
224
+ path instead. Only set it if you always want users to land on the same page, and leave it unset to
225
+ return users to where they were. `redirectToAfterSignUp` behaves the same way for sign-up.
226
+
227
+ ```typescript title="zudoku.config.ts"
228
+ {
229
+ authentication: {
230
+ type: "auth0",
231
+ // ...
232
+ // Omit to return users to the page they came from
233
+ redirectToAfterSignIn: "/docs",
234
+ },
235
+ }
236
+ ```
237
+
238
+ This applies to all built-in providers. For Supabase social (OAuth) sign-in, the return URL must
239
+ also be allowed under **Redirect URLs** in your Supabase project's authentication settings, and a
240
+ return URL on another origin falls back to your site's root.
241
+
217
242
  ## Protected Routes
218
243
 
219
244
  Once authentication is configured, you can protect specific routes in your documentation to require
@@ -143,7 +143,8 @@ footer: {
143
143
  dark: "/path/to/dark-logo.png"
144
144
  },
145
145
  alt: "Company Logo",
146
- width: "120px" // optional width
146
+ width: 120, // optional intrinsic width
147
+ height: 24 // optional intrinsic height; set both to prevent layout shift
147
148
  }
148
149
  }
149
150
  ```
@@ -208,7 +209,8 @@ footer: {
208
209
  dark: "/images/logo-dark.svg"
209
210
  },
210
211
  alt: "Company Logo",
211
- width: "100px"
212
+ width: 100,
213
+ height: 24
212
214
  }
213
215
  }
214
216
  ```
@@ -45,7 +45,15 @@ authenticated to access these routes.
45
45
 
46
46
  When a user tries to access a protected route, a login dialog will appear prompting them to sign in
47
47
  or register. After logging in, they are automatically redirected back to the route they were trying
48
- to access.
48
+ to access, including its query string.
49
+
50
+ :::caution{title="redirectToAfterSignIn takes precedence"}
51
+
52
+ If `authentication.redirectToAfterSignIn` is set, users are sent to that path after every sign-in
53
+ instead of the page they were trying to open. Leave it unset to return users to where they were. See
54
+ [Redirects after sign-in](./authentication.md#redirects-after-sign-in).
55
+
56
+ :::
49
57
 
50
58
  ## Object Format
51
59
 
@@ -58,7 +58,8 @@ Configure the site's logo with different versions for light and dark themes:
58
58
  dark: "/dark-logo.png"
59
59
  },
60
60
  alt: "Company Logo",
61
- width: "120px", // optional width
61
+ width: 120, // optional intrinsic width
62
+ height: 32, // optional intrinsic height; set both to prevent layout shift
62
63
  href: "/", // optional link target (defaults to "/")
63
64
  reloadDocument: true, // optional, defaults to true
64
65
  }
@@ -19,6 +19,14 @@ For information on how to configure processors in your project, see the
19
19
 
20
20
  Dev Portal provides several built-in processors that you can use to transform your schemas:
21
21
 
22
+ :::note
23
+
24
+ Items marked with [`x-internal`](../openapi-extensions/x-internal) are removed automatically in
25
+ every build, so you don't need to configure `removePaths` or `removeParameters` for that. The
26
+ `x-internal` examples below show how the processors work.
27
+
28
+ :::
29
+
22
30
  ### `removeExtensions`
23
31
 
24
32
  Removes OpenAPI extensions (`x-` prefixed properties) from your schema:
@@ -0,0 +1,88 @@
1
+ ---
2
+ title: x-internal
3
+ sidebar_icon: eye-off
4
+ ---
5
+
6
+ Use `x-internal` to hide internal endpoints and parameters from your API documentation. Anything
7
+ marked with `x-internal: true` is removed from the schema before Dev Portal renders it, so it doesn't
8
+ show up in the navigation, on operation pages, in the playground, or in documents published with
9
+ [`publish`](/dev-portal/zudoku/configuration/api-reference#publish-a-canonical-openapi-document).
10
+
11
+ `x-internal` is built in and applies to every Dev Portal project. You don't need to add a
12
+ [schema processor](/dev-portal/zudoku/guides/processors) for it.
13
+
14
+ :::warning
15
+
16
+ `x-internal` only affects the documentation. The endpoints still exist on your API and can still be
17
+ called. Don't rely on it to secure anything.
18
+
19
+ :::
20
+
21
+ ## Location
22
+
23
+ The extension can be added at the following levels:
24
+
25
+ | Level | Effect |
26
+ | -------------------- | ----------------------------------------------------------------- |
27
+ | **Path Item Object** | Removes the whole path, including all of its operations. |
28
+ | **Operation Object** | Removes only that operation. Other methods on the same path stay. |
29
+ | **Parameter Object** | Removes the parameter from the path item or operation. |
30
+
31
+ | Option | Type | Description |
32
+ | ------------ | --------- | ---------------------------------------------------- |
33
+ | `x-internal` | `boolean` | Set to `true` to remove the item from documentation. |
34
+
35
+ `$ref`s are not resolved, so add `x-internal` to the parameter where it is used rather than to a
36
+ shared `components.parameters` entry.
37
+
38
+ Other objects such as tags, schemas, schema properties and responses are not covered. Use a custom
39
+ [schema processor](/dev-portal/zudoku/guides/processors#custom-processors) if you need to hide those.
40
+
41
+ ## Example
42
+
43
+ ```yaml
44
+ paths:
45
+ /admin:
46
+ x-internal: true # hides the entire path
47
+ get:
48
+ summary: Admin dashboard
49
+ responses:
50
+ "200":
51
+ description: OK
52
+ /users:
53
+ get:
54
+ summary: List users
55
+ parameters:
56
+ - name: limit
57
+ in: query
58
+ schema:
59
+ type: integer
60
+ - name: debug
61
+ in: query
62
+ x-internal: true # hides only this parameter
63
+ schema:
64
+ type: boolean
65
+ responses:
66
+ "200":
67
+ description: OK
68
+ delete:
69
+ summary: Delete all users
70
+ x-internal: true # hides only this operation
71
+ responses:
72
+ "204":
73
+ description: Deleted
74
+ ```
75
+
76
+ In this example, the documentation shows `GET /users` with only the `limit` parameter. The `/admin`
77
+ path, the `DELETE /users` operation, and the `debug` parameter are all hidden.
78
+
79
+ ## Notes
80
+
81
+ - `x-internal` applies to APIs loaded from files (`type: "file"`), the same as other
82
+ [schema processors](/dev-portal/zudoku/guides/processors). Schemas loaded from a URL are not processed.
83
+ - Your own schema processors in `zudoku.build.ts` run first, so they can add `x-internal` to items
84
+ programmatically.
85
+ - The [`schemaDownload`](/dev-portal/zudoku/configuration/api-reference#options) option serves your original
86
+ schema file, which still contains the items marked with `x-internal`.
87
+ - There is currently no option to turn this behavior off. If you need to keep an item in your
88
+ documentation, remove its `x-internal` flag.
@@ -114,6 +114,9 @@ curl https://gateway.example.com/v1/chat/completions \
114
114
 
115
115
  Authentication scheme matching is case-insensitive. A missing key, an invalid
116
116
  scheme, or a key that is not authorized receives a `401 Unauthorized` response.
117
+ The 401 carries a `WWW-Authenticate` challenge that names the expected scheme
118
+ and, when it is not `Authorization`, the header. See
119
+ [Unauthorized responses](#unauthorized-responses).
117
120
 
118
121
  Once the key is accepted, the policy removes the `authHeader` header from the
119
122
  request. The application key never reaches an upstream provider or a policy
@@ -221,6 +224,28 @@ applies: `authHeader` and `authScheme` select the Zuplo key, and providers use
221
224
  their configured credentials. Moving the gateway key to an arbitrary custom
222
225
  header alone does not enable passthrough.
223
226
 
227
+ ## Unauthorized responses
228
+
229
+ Every 401 from this policy carries a `WWW-Authenticate` challenge built from the
230
+ policy options, so a client learns where the key goes without seeing the
231
+ configuration. The scheme is `authScheme`, or `ApiKey` when `authScheme` is
232
+ empty and the header carries only the key. A `header` parameter names
233
+ `authHeader` when it is not `Authorization`. This policy's own 403 responses
234
+ carry no challenge. On a User App route, the fail-closed 403 carries the same
235
+ `WWW-Authenticate` challenge when this policy refused the key.
236
+
237
+ | Options | `WWW-Authenticate` |
238
+ | ------------------------------------------------- | --------------------------------------------------- |
239
+ | `{}` | `Bearer realm="ai-gateway"` |
240
+ | `{ "authScheme": "Token" }` | `Token realm="ai-gateway"` |
241
+ | `{ "authHeader": "x-gateway-key" }` | `Bearer realm="ai-gateway", header="x-gateway-key"` |
242
+ | `{ "authHeader": "x-api-key", "authScheme": "" }` | `ApiKey realm="ai-gateway", header="x-api-key"` |
243
+
244
+ With `credentialPassthrough` enabled, the challenge adds
245
+ `passthrough="Authorization"` to say the provider credential goes in
246
+ `Authorization`, for example
247
+ `ApiKey realm="ai-gateway", header="zp-gateway-api-key", passthrough="Authorization"`.
248
+
224
249
  ## Choose a cache duration
225
250
 
226
251
  `cacheTtlSeconds` controls how long an authentication result can be reused. The
@@ -73,7 +73,8 @@
73
73
  "default": "Bearer",
74
74
  "x-show-example": false,
75
75
  "x-advanced": true,
76
- "description": "The scheme that prefixes the key in the authHeader header, for example Bearer. Set to an empty string when the header contains only the key."
76
+ "pattern": "^(\\$env\\([^)]+\\)|[!#$%&'*+.^_`|~0-9A-Za-z-]*)$",
77
+ "description": "The scheme that prefixes the key in the authHeader header, for example Bearer. Set to an empty string when the header contains only the key. The scheme must be a single HTTP token such as Bearer, or empty for a bare key. $env(NAME) is accepted and validated after substitution."
77
78
  },
78
79
  "credentialPassthrough": {
79
80
  "type": "boolean",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zuplo",
3
- "version": "7.9.6",
3
+ "version": "7.9.9",
4
4
  "type": "module",
5
5
  "description": "The official Zuplo CLI for local development and platform management",
6
6
  "homepage": "https://zuplo.com/docs/cli/overview",
@@ -32,9 +32,9 @@
32
32
  "zuplo": "zuplo.js"
33
33
  },
34
34
  "dependencies": {
35
- "@zuplo/cli": "7.9.6",
36
- "@zuplo/core": "7.9.6",
37
- "@zuplo/runtime": "7.9.6",
38
- "@zuplo/test": "7.9.6"
35
+ "@zuplo/cli": "7.9.9",
36
+ "@zuplo/core": "7.9.9",
37
+ "@zuplo/runtime": "7.9.9",
38
+ "@zuplo/test": "7.9.9"
39
39
  }
40
40
  }