aspera-cli 4.27.5 → 4.28.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 (139) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +160 -4
  4. data/CONTRIBUTING.md +4 -2
  5. data/README.md +1 -1
  6. data/bin/asession +1 -1
  7. data/docs/README.md +1086 -331
  8. data/docs/test-mcp-with-ai.md +5 -3
  9. data/lib/aspera/agent/direct.rb +15 -4
  10. data/lib/aspera/agent/factory.rb +2 -1
  11. data/lib/aspera/agent/node.rb +1 -1
  12. data/lib/aspera/api/cos_node.rb +1 -1
  13. data/lib/aspera/api/faspex.rb +1 -1
  14. data/lib/aspera/api/node.rb +6 -2
  15. data/lib/aspera/ascp/installation.rb +47 -11
  16. data/lib/aspera/ascp/management.rb +89 -43
  17. data/lib/aspera/cli/ascp_actions.rb +5 -19
  18. data/lib/aspera/cli/bootstrapper.rb +1 -2
  19. data/lib/aspera/cli/command_registry.rb +43 -3
  20. data/lib/aspera/cli/command_spec.rb +3 -0
  21. data/lib/aspera/cli/completion/ascli.bash +39 -5
  22. data/lib/aspera/cli/completion/ascli.fish +16 -8
  23. data/lib/aspera/cli/completion/ascli.ps1 +41 -0
  24. data/lib/aspera/cli/completion/ascli.zsh +20 -4
  25. data/lib/aspera/cli/completion_actions.rb +360 -0
  26. data/lib/aspera/cli/error.rb +42 -0
  27. data/lib/aspera/cli/extended_value.rb +30 -5
  28. data/lib/aspera/cli/formatter.rb +118 -56
  29. data/lib/aspera/cli/hints.rb +0 -1
  30. data/lib/aspera/cli/http.rb +6 -5
  31. data/lib/aspera/cli/info.rb +10 -4
  32. data/lib/aspera/cli/mailer.rb +1 -1
  33. data/lib/aspera/cli/mcp/http_servlet.rb +156 -0
  34. data/lib/aspera/cli/mcp/secrets.rb +143 -0
  35. data/lib/aspera/cli/mcp/tool.rb +231 -0
  36. data/lib/aspera/cli/option_value.rb +9 -1
  37. data/lib/aspera/cli/options.schema.yaml +390 -39
  38. data/lib/aspera/cli/parser.rb +14 -5
  39. data/lib/aspera/cli/plugins/aoc.rb +8 -11
  40. data/lib/aspera/cli/plugins/base.rb +36 -15
  41. data/lib/aspera/cli/plugins/config.rb +15 -44
  42. data/lib/aspera/cli/plugins/console.rb +3 -1
  43. data/lib/aspera/cli/plugins/factory.rb +1 -1
  44. data/lib/aspera/cli/plugins/faspex5.rb +9 -19
  45. data/lib/aspera/cli/plugins/faspio.rb +36 -5
  46. data/lib/aspera/cli/plugins/httpgw.rb +1 -0
  47. data/lib/aspera/cli/plugins/mcp.rb +177 -118
  48. data/lib/aspera/cli/plugins/node.rb +14 -8
  49. data/lib/aspera/cli/plugins/orchestrator.rb +351 -38
  50. data/lib/aspera/cli/plugins/server.rb +3 -1
  51. data/lib/aspera/cli/plugins/shares.rb +205 -35
  52. data/lib/aspera/cli/preset_actions.rb +15 -7
  53. data/lib/aspera/cli/preset_manager.rb +24 -2
  54. data/lib/aspera/cli/prompt.rb +3 -1
  55. data/lib/aspera/cli/result.rb +17 -4
  56. data/lib/aspera/cli/runner.rb +133 -43
  57. data/lib/aspera/cli/security.rb +134 -0
  58. data/lib/aspera/cli/table_fitter.rb +116 -0
  59. data/lib/aspera/cli/terminal_formatter.rb +23 -34
  60. data/lib/aspera/cli/transfer_agent.rb +4 -1
  61. data/lib/aspera/cli/vault_manager.rb +6 -5
  62. data/lib/aspera/cli/version.rb +1 -1
  63. data/lib/aspera/cli/web_secret.html.erb +61 -0
  64. data/lib/aspera/cli/web_secret.rb +220 -0
  65. data/lib/aspera/cli/wizard.rb +19 -9
  66. data/lib/aspera/command_line_builder.rb +26 -0
  67. data/lib/aspera/data_repository.rb +38 -24
  68. data/lib/aspera/duration.rb +42 -0
  69. data/lib/aspera/environment.rb +88 -24
  70. data/lib/aspera/exec_spec.rb +6 -5
  71. data/lib/aspera/faspex_gw.rb +98 -32
  72. data/lib/aspera/faspex_postproc.rb +187 -44
  73. data/lib/aspera/formatter_interface.rb +0 -1
  74. data/lib/aspera/id_generator.rb +2 -1
  75. data/lib/aspera/json_rpc/client.rb +51 -32
  76. data/lib/aspera/json_rpc/version.rb +1 -0
  77. data/lib/aspera/keychain/base.rb +5 -0
  78. data/lib/aspera/keychain/encrypted_hash.rb +6 -2
  79. data/lib/aspera/keychain/factory.rb +2 -3
  80. data/lib/aspera/keychain/hashicorp_vault.rb +7 -4
  81. data/lib/aspera/keychain/macos_security.rb +119 -13
  82. data/lib/aspera/keychain/one_password_api.rb +8 -3
  83. data/lib/aspera/keychain/one_password_base.rb +14 -9
  84. data/lib/aspera/keychain/one_password_cli.rb +4 -2
  85. data/lib/aspera/log.rb +3 -6
  86. data/lib/aspera/markdown.rb +152 -115
  87. data/lib/aspera/mime.rb +6 -0
  88. data/lib/aspera/nagios.rb +3 -1
  89. data/lib/aspera/node_emulator.rb +98 -101
  90. data/lib/aspera/oauth/{base.rb → client/base.rb} +5 -4
  91. data/lib/aspera/oauth/{boot.rb → client/boot.rb} +3 -2
  92. data/lib/aspera/oauth/{factory.rb → client/factory.rb} +7 -0
  93. data/lib/aspera/oauth/{generic.rb → client/generic.rb} +1 -1
  94. data/lib/aspera/oauth/{json_credentials.rb → client/json_credentials.rb} +1 -1
  95. data/lib/aspera/oauth/{jwt.rb → client/jwt.rb} +1 -1
  96. data/lib/aspera/oauth/{url_json.rb → client/url_json.rb} +1 -1
  97. data/lib/aspera/oauth/{web.rb → client/web.rb} +2 -2
  98. data/lib/aspera/oauth/server/authorize.html.erb +34 -0
  99. data/lib/aspera/oauth/server/pkce.rb +426 -0
  100. data/lib/aspera/orchestrator_workflow_checker.rb +561 -0
  101. data/lib/aspera/preview/terminal.rb +3 -2
  102. data/lib/aspera/rainbow.rb +27 -1
  103. data/lib/aspera/rest/aspera_errors.rb +51 -59
  104. data/lib/aspera/rest/client.rb +21 -14
  105. data/lib/aspera/rest/error_analyzer.rb +9 -0
  106. data/lib/aspera/rest/list.rb +6 -6
  107. data/lib/aspera/rest/util.rb +7 -1
  108. data/lib/aspera/rest.rb +0 -1
  109. data/lib/aspera/schema/IBM Aspera Faspex API-5.0-enhanced.yaml +0 -2
  110. data/lib/aspera/schema/IBM Aspera Orchestrator API-v1-enhanced.yaml +4001 -0
  111. data/lib/aspera/schema/IBM Aspera faspio Gateway API-1.0.0-enhanced.yaml +1097 -0
  112. data/lib/aspera/schema/IBM Aspera on Cloud Automation API-1.0.5-enhanced.yaml +35 -35
  113. data/lib/aspera/schema/IBM_Aspera_Shares.yaml +819 -7
  114. data/lib/aspera/schema/documentation.rb +50 -78
  115. data/lib/aspera/schema/reader.rb +39 -11
  116. data/lib/aspera/schema/registry.rb +8 -2
  117. data/lib/aspera/secret_hider.rb +94 -15
  118. data/lib/aspera/secret_strength.rb +114 -0
  119. data/lib/aspera/servlet_helpers.rb +111 -0
  120. data/lib/aspera/sync/args.schema.yaml +3 -1
  121. data/lib/aspera/sync/conf.schema.yaml +16 -6
  122. data/lib/aspera/sync/operations.rb +21 -1
  123. data/lib/aspera/temp_file_manager.rb +79 -20
  124. data/lib/aspera/transfer/parameters.rb +5 -0
  125. data/lib/aspera/transfer/spec.rb +52 -12
  126. data/lib/aspera/transfer/spec.schema.yaml +8 -5
  127. data/lib/aspera/web_auth/index.html.erb +16 -0
  128. data/lib/aspera/web_auth/server.rb +18 -10
  129. data/lib/aspera/web_page.html.erb +262 -0
  130. data/lib/aspera/web_page.rb +61 -0
  131. data/lib/aspera/web_server_simple.rb +76 -10
  132. data.tar.gz.sig +0 -0
  133. metadata +47 -32
  134. metadata.gz.sig +0 -0
  135. data/lib/aspera/cli/mcp_tool.rb +0 -189
  136. data/lib/aspera/oauth.rb +0 -9
  137. data/lib/aspera/schema/IBM Aspera Orchestrator API-v1.yaml +0 -1784
  138. data/lib/aspera/schema/IBM Aspera faspio Gateway API-1.0.0.yaml +0 -249
  139. data/lib/aspera/web_auth/index.html +0 -147
@@ -0,0 +1,1097 @@
1
+ # DO NOT EDIT THIS FILE MANUALLY
2
+ # This file is automatically downloaded from:
3
+ # https://raw.githubusercontent.com/laurent-martin/aspera-api-examples/refs/heads/main/openapi/IBM%20Aspera%20faspio%20Gateway%20API-1.0.0-enhanced.yaml
4
+ # Use 'rake tools:openapi' to update this file
5
+
6
+ openapi: 3.1.0
7
+ info:
8
+ title: IBM Aspera faspio Gateway API
9
+ description: |
10
+ REST API for managing IBM Aspera faspio Gateway bridges and monitoring.
11
+
12
+ ## Overview
13
+ IBM Aspera faspio Gateway bridges local TCP or UDP connections over the FASP (Fast, Adaptive, and Secure Protocol)
14
+ transport to a remote gateway peer. You can use this API to create, inspect, and delete **dynamic**
15
+ bridges at runtime without restarting the gateway.
16
+
17
+ Static bridges (defined in `gateway.toml`) are read-only via this API — they can be retrieved
18
+ but cannot be deleted or modified.
19
+
20
+ ## Authentication
21
+ The API supports three authentication modes, configured in `gateway.toml` under `[admin]`:
22
+
23
+ | Mode | Description |
24
+ |------|-------------|
25
+ | `none` | No authentication (development only) |
26
+ | `basic` | HTTP Basic Authentication (username + SHA-512/PBKDF2 password digest) |
27
+ | `oauth2` | Bearer JWT token obtained via `POST /auth/token` |
28
+
29
+ ## OAuth 2.0 quick start
30
+
31
+ This gateway implements the **JWT Bearer grant** (RFC 7523). There is no identity provider
32
+ involved — the gateway itself issues and verifies tokens using RSA key pairs you generate.
33
+
34
+ ### Step 1 — Generate key pairs
35
+
36
+ The gateway needs **two** RSA key pairs:
37
+
38
+ | Key pair | Who holds it | Purpose |
39
+ |----------|-------------|---------|
40
+ | **Client key pair** | Your application | Sign JWT assertions sent to `POST /auth/token` |
41
+ | **Server key pair** | The gateway | Sign access tokens returned to your application |
42
+
43
+ ```bash
44
+ # Client key pair (your application uses the private key to sign assertions)
45
+ openssl genrsa -out client_private.pem 2048
46
+ openssl rsa -in client_private.pem -pubout -out client_public.pem
47
+
48
+ # Server key pair (the gateway uses the private key to sign access tokens)
49
+ openssl genrsa -out server_private.pem 2048
50
+ openssl rsa -in server_private.pem -pubout -out server_public.pem
51
+ ```
52
+
53
+ ### Step 2 — Configure `gateway.toml`
54
+
55
+ Give the gateway the **client's public key** (to verify assertions) and the
56
+ **server's private key** (to sign access tokens):
57
+
58
+ ```toml
59
+ [admin]
60
+ rest_api_auth = "oauth2"
61
+ rest_api_enabled = true
62
+
63
+ [admin.oauth2]
64
+ client_id = "my-gateway-client"
65
+ jwt_grant_enabled = true
66
+ jwt_verification_key = "/etc/faspio-gateway/client_public.pem" # verifies your assertion
67
+ jwt_signing_key = "/etc/faspio-gateway/server_private.pem" # signs the access token
68
+ ```
69
+
70
+ ### Step 3 — Create a JWT assertion
71
+
72
+ Your application signs a short-lived JWT with its **private key**.
73
+ The `iss` and `sub` claims must both equal the `client_id` in `gateway.toml`.
74
+
75
+ Example using Python (PyJWT):
76
+ ```python
77
+ import jwt, time
78
+
79
+ with open("client_private.pem") as f:
80
+ private_key = f.read()
81
+
82
+ assertion = jwt.encode(
83
+ {"iss": "my-gateway-client", "sub": "my-gateway-client",
84
+ "exp": int(time.time()) + 300}, # valid for 5 minutes
85
+ private_key,
86
+ algorithm="RS256"
87
+ )
88
+ ```
89
+
90
+ Example using `openssl` + `bash` (no extra libraries):
91
+ ```bash
92
+ HEADER=$(echo -n '{"alg":"RS256","typ":"JWT"}' | base64url)
93
+ NOW=$(date +%s); EXP=$((NOW + 300))
94
+ PAYLOAD=$(echo -n "{\"iss\":\"my-gateway-client\",\"sub\":\"my-gateway-client\",\"exp\":$EXP}" | base64url)
95
+ SIG=$(echo -n "$HEADER.$PAYLOAD" | openssl dgst -sha256 -sign client_private.pem | base64url)
96
+ ASSERTION="$HEADER.$PAYLOAD.$SIG"
97
+ ```
98
+
99
+ ### Step 4 — Exchange the assertion for an access token
100
+
101
+ ```bash
102
+ curl -s -X POST http://127.0.0.1:8080/auth/token \
103
+ -H "Content-Type: application/json" \
104
+ -d "{\"grant_type\":\"urn:ietf:params:oauth:grant-type:jwt-bearer\",
105
+ \"assertion\":\"$ASSERTION\",
106
+ \"client_id\":\"my-gateway-client\"}"
107
+ ```
108
+
109
+ Response:
110
+ ```json
111
+ {
112
+ "access_token": "<TOKEN>",
113
+ "token_type": "Bearer",
114
+ "expires_in": 3600
115
+ }
116
+ ```
117
+
118
+ ### Step 5 — Call the API with the access token
119
+
120
+ ```bash
121
+ TOKEN="<TOKEN>"
122
+
123
+ # List all bridges
124
+ curl -s http://127.0.0.1:8080/bridges \
125
+ -H "Authorization: Bearer $TOKEN"
126
+
127
+ # Create a bridge
128
+ curl -s -X POST http://127.0.0.1:8080/bridges \
129
+ -H "Authorization: Bearer $TOKEN" \
130
+ -H "Content-Type: application/json" \
131
+ -d '{"name":"Bridge-1","local":{"bind_address":"127.0.0.1","port":"2000","protocol":"tcp","tls_enabled":false},"forward":{"host":["10.0.0.2"],"port":"3000","protocol":"fasp","tls_enabled":false}}'
132
+ ```
133
+
134
+ The access token expires after **1 hour** (`expires_in: 3600`). Repeat steps 3–4 to renew it.
135
+
136
+ ## Bridge lifecycle
137
+ ```text
138
+ POST /bridges
139
+ ↓
140
+ (bridge created and started)
141
+ ↓
142
+ GET /bridges/{id}
143
+ ↓
144
+ DELETE /bridges/{id}
145
+ ↓
146
+ (bridge stopped and removed)
147
+ ```
148
+
149
+ Bridges created via the API are **dynamic** — they are persisted to a runtime state file
150
+ and survive gateway restarts.
151
+ contact:
152
+ name: IBM Aspera Support
153
+ email: Aspera-client-team@wwpdl.vnet.ibm.com
154
+ license:
155
+ name: © IBM. All rights reserved
156
+ url: https://www-40.ibm.com/software/sla/sladb.nsf/displaylis/0CF8A1C0BA2B994C002587F70069A8B5?OpenDocument
157
+ version: 1.0.0
158
+ servers:
159
+ - url: http://127.0.0.1:8080
160
+ description: Default local gateway admin endpoint (HTTP)
161
+ - url: https://127.0.0.1:8080
162
+ description: Default local gateway admin endpoint (HTTPS/TLS)
163
+ paths:
164
+ # ---------------------------------------------------------------------------
165
+ # Health
166
+ # ---------------------------------------------------------------------------
167
+ /ping:
168
+ get:
169
+ operationId: ping
170
+ summary: Liveness probe
171
+ description: |
172
+ Returns an empty JSON object `{}` when the gateway HTTP server is running.
173
+ This endpoint does **not** require authentication and is not subject to the
174
+ configured `rest_api_auth` scheme — it can be used by load balancers and
175
+ orchestrators for health checks.
176
+ # Note: /ping is intentionally unauthenticated — no 4xx responses apply.
177
+ # The linter warning `operation-4xx-response` is suppressed by design.
178
+ responses:
179
+ '200':
180
+ description: The gateway is running.
181
+ headers:
182
+ Cache-Control:
183
+ description: Always `no-cache` — do not cache liveness responses.
184
+ schema:
185
+ type: string
186
+ examples:
187
+ - no-cache
188
+ content:
189
+ application/json:
190
+ schema:
191
+ description: Empty JSON object.
192
+ type: object
193
+ examples:
194
+ - {}
195
+ security: [] # Explicitly unauthenticated
196
+ tags:
197
+ - Health
198
+ options:
199
+ tags:
200
+ - Health
201
+ summary: CORS preflight for /ping
202
+ description: Handles browser CORS preflight requests for the `/ping` endpoint.
203
+ operationId: pingOptions
204
+ security: []
205
+ # Note: OPTIONS preflight responses never return 4xx by CORS spec design.
206
+ responses:
207
+ '204':
208
+ description: No Content — CORS headers returned.
209
+ headers:
210
+ Access-Control-Allow-Origin:
211
+ schema:
212
+ type: string
213
+ examples:
214
+ - '*'
215
+ Access-Control-Allow-Methods:
216
+ schema:
217
+ type: string
218
+ examples:
219
+ - DELETE, GET, PUT, POST
220
+ Access-Control-Allow-Headers:
221
+ schema:
222
+ type: string
223
+ examples:
224
+ - Authorization, Content-Type
225
+ # ---------------------------------------------------------------------------
226
+ # Bridges — collection
227
+ # ---------------------------------------------------------------------------
228
+ /bridges:
229
+ get:
230
+ operationId: getBridges
231
+ summary: List all bridges
232
+ description: |
233
+ Returns an array of all configured bridges — both **static** (from `gateway.toml`)
234
+ and **dynamic** (created via `POST /bridges`).
235
+
236
+ An empty gateway returns `[]`.
237
+ responses:
238
+ '200':
239
+ description: Array of bridge configurations (may be empty).
240
+ content:
241
+ application/json:
242
+ schema:
243
+ type: array
244
+ items:
245
+ $ref: '#/components/schemas/BridgeResponse'
246
+ examples:
247
+ empty:
248
+ summary: No bridges configured
249
+ value: []
250
+ single_tcp_fasp:
251
+ summary: One TCP→FASP bridge
252
+ value:
253
+ - id: '1'
254
+ name: Bridge-1
255
+ source: dynamic
256
+ local:
257
+ bind_address: 127.0.0.1
258
+ port:
259
+ - 2000
260
+ - 2001
261
+ protocol: tcp
262
+ tls_enabled: false
263
+ forward:
264
+ host:
265
+ - gw2.example.com
266
+ - 10.0.0.2
267
+ port:
268
+ - 3000
269
+ - 3001
270
+ protocol: fasp
271
+ tls_enabled: false
272
+ '401':
273
+ $ref: '#/components/responses/Unauthorized'
274
+ tags:
275
+ - Bridges
276
+ post:
277
+ operationId: createBridge
278
+ summary: Create a new bridge
279
+ description: |
280
+ Creates a new **dynamic** bridge, starts it immediately, and persists it to the
281
+ runtime state file so it survives a gateway restart.
282
+
283
+ ### Port syntax
284
+ The `port` field of the request body accepts either:
285
+ - A single port number as a string: `"2000"`
286
+ - A contiguous range: `"2000-2003"` (expands to ports 2000, 2001, 2002, 2003)
287
+
288
+ ### Protocol combinations
289
+ | Local protocol | Forward protocol | Description |
290
+ |---------------|-----------------|-------------|
291
+ | `tcp` | `fasp` | Most common: accelerate TCP over FASP |
292
+ | `udp` | `fasp` | Accelerate UDP over FASP |
293
+ | `tcp` | `tcp` | TCP relay (no acceleration) |
294
+ | `udp` | `udp` | UDP relay |
295
+
296
+ ### Static bridge limitation
297
+ This endpoint only creates dynamic bridges. Static bridges defined in `gateway.toml`
298
+ cannot be created via the API.
299
+ requestBody:
300
+ description: Bridge configuration to create.
301
+ required: true
302
+ content:
303
+ application/json:
304
+ schema:
305
+ $ref: '#/components/schemas/BridgeRequest'
306
+ examples:
307
+ tcp_to_fasp:
308
+ summary: Forward local TCP traffic over FASP
309
+ value:
310
+ name: Bridge-1
311
+ local:
312
+ bind_address: 127.0.0.1
313
+ port: 2000-2001
314
+ protocol: tcp
315
+ tls_enabled: false
316
+ forward:
317
+ host:
318
+ - gw2.example.com
319
+ - 10.0.0.2
320
+ port: 3000-3001
321
+ protocol: fasp
322
+ tls_enabled: false
323
+ udp_to_fasp:
324
+ summary: Forward local UDP traffic over FASP
325
+ value:
326
+ name: Bridge-UDP
327
+ local:
328
+ bind_address: 0.0.0.0
329
+ port: '4000'
330
+ protocol: udp
331
+ tls_enabled: false
332
+ forward:
333
+ host:
334
+ - 10.0.0.2
335
+ port: '5000'
336
+ protocol: fasp
337
+ tls_enabled: true
338
+ responses:
339
+ '201':
340
+ description: Bridge created and started successfully.
341
+ content:
342
+ application/json:
343
+ schema:
344
+ $ref: '#/components/schemas/BridgeResponse'
345
+ '401':
346
+ $ref: '#/components/responses/Unauthorized'
347
+ '415':
348
+ $ref: '#/components/responses/UnsupportedMediaType'
349
+ '422':
350
+ $ref: '#/components/responses/UnprocessableEntity'
351
+ '500':
352
+ $ref: '#/components/responses/InternalServerError'
353
+ tags:
354
+ - Bridges
355
+ options:
356
+ tags:
357
+ - Bridges
358
+ summary: CORS preflight for /bridges
359
+ operationId: bridgesOptions
360
+ security: []
361
+ # Note: OPTIONS preflight responses never return 4xx by CORS spec design.
362
+ responses:
363
+ '204':
364
+ description: No Content — CORS headers returned.
365
+ # ---------------------------------------------------------------------------
366
+ # Bridges — single resource
367
+ # ---------------------------------------------------------------------------
368
+ /bridges/{id}:
369
+ parameters:
370
+ - $ref: '#/components/parameters/BridgeId'
371
+ get:
372
+ operationId: getBridgeById
373
+ summary: Get a bridge by ID
374
+ description: |
375
+ Returns the full configuration of a single bridge identified by `id`.
376
+ Works for both static and dynamic bridges.
377
+ responses:
378
+ '200':
379
+ description: Bridge configuration.
380
+ content:
381
+ application/json:
382
+ schema:
383
+ $ref: '#/components/schemas/BridgeResponse'
384
+ example:
385
+ id: '1'
386
+ name: Bridge-1
387
+ source: dynamic
388
+ local:
389
+ bind_address: 127.0.0.1
390
+ port:
391
+ - 2000
392
+ - 2001
393
+ protocol: tcp
394
+ tls_enabled: false
395
+ forward:
396
+ host:
397
+ - gw2.example.com
398
+ port:
399
+ - 3000
400
+ - 3001
401
+ protocol: fasp
402
+ tls_enabled: false
403
+ '400':
404
+ $ref: '#/components/responses/BadRequest'
405
+ '401':
406
+ $ref: '#/components/responses/Unauthorized'
407
+ '404':
408
+ $ref: '#/components/responses/NotFound'
409
+ tags:
410
+ - Bridges
411
+ delete:
412
+ operationId: deleteBridgeById
413
+ summary: Delete a bridge
414
+ description: |
415
+ Stops and removes a **dynamic** bridge by its `id`.
416
+
417
+ - Returns `204 No Content` on success.
418
+ - Returns `403 Forbidden` if the bridge is **static** (defined in `gateway.toml`) —
419
+ static bridges cannot be deleted via the API; edit the configuration file instead.
420
+ - Returns `404 Not Found` if no bridge with the given `id` exists.
421
+ responses:
422
+ '204':
423
+ description: Bridge stopped and deleted successfully. No response body.
424
+ '400':
425
+ $ref: '#/components/responses/BadRequest'
426
+ '401':
427
+ $ref: '#/components/responses/Unauthorized'
428
+ '403':
429
+ $ref: '#/components/responses/Forbidden'
430
+ '404':
431
+ $ref: '#/components/responses/NotFound'
432
+ '500':
433
+ $ref: '#/components/responses/InternalServerError'
434
+ tags:
435
+ - Bridges
436
+ put:
437
+ operationId: updateBridgeById
438
+ summary: Update a bridge (not yet implemented)
439
+ description: |
440
+ **Not implemented.** Reserved for future use.
441
+
442
+ When implemented, this endpoint will update only **dynamic** bridges.
443
+ Attempting to update a **static** bridge will return `403 Forbidden`.
444
+ requestBody:
445
+ required: true
446
+ content:
447
+ application/json:
448
+ schema:
449
+ $ref: '#/components/schemas/BridgeRequest'
450
+ # Note: PUT is not yet implemented — no 2xx response exists by design.
451
+ # The linter warning `operation-2xx-response` is suppressed by design.
452
+ responses:
453
+ '400':
454
+ $ref: '#/components/responses/BadRequest'
455
+ '401':
456
+ $ref: '#/components/responses/Unauthorized'
457
+ '403':
458
+ $ref: '#/components/responses/Forbidden'
459
+ '404':
460
+ $ref: '#/components/responses/NotFound'
461
+ '501':
462
+ description: Not Implemented — this endpoint is reserved for a future release.
463
+ tags:
464
+ - Bridges
465
+ options:
466
+ tags:
467
+ - Bridges
468
+ summary: CORS preflight for /bridges/{id}
469
+ operationId: bridgeByIdOptions
470
+ security: []
471
+ # Note: OPTIONS preflight responses never return 4xx by CORS spec design.
472
+ responses:
473
+ '204':
474
+ description: No Content — CORS headers returned.
475
+ # ---------------------------------------------------------------------------
476
+ # OAuth 2.0 token endpoint
477
+ # ---------------------------------------------------------------------------
478
+ /auth/token:
479
+ post:
480
+ operationId: createAccessToken
481
+ summary: Request an OAuth 2.0 access token
482
+ description: |
483
+ Issues a signed JWT access token using the
484
+ **JWT Bearer grant type** (`urn:ietf:params:oauth:grant-type:jwt-bearer`).
485
+
486
+ The client must supply a signed JWT assertion (signed with the client's private RSA key).
487
+ The gateway verifies the assertion against the configured `jwt_verification_key`, then
488
+ issues a short-lived RS256-signed JWT (default: 1 hour) signed with `jwt_signing_key`.
489
+
490
+ Supports two content types:
491
+ - `application/json` — fields as a JSON object body
492
+ - `application/x-www-form-urlencoded` — fields as URL-encoded form body
493
+
494
+ This endpoint is only available when `rest_api_auth = "oauth2"` is configured in
495
+ `gateway.toml`. It does **not** require a bearer token itself.
496
+
497
+ ### JWT assertion requirements
498
+ The JWT assertion must contain:
499
+ - `iss` (issuer): the `client_id` configured in `gateway.toml`
500
+ - `sub` (subject): the `client_id` configured in `gateway.toml`
501
+ - `exp` (expiration): a future timestamp
502
+
503
+ The signature must be verifiable with the public key at `jwt_verification_key`.
504
+ requestBody:
505
+ required: true
506
+ content:
507
+ application/json:
508
+ schema:
509
+ $ref: '#/components/schemas/TokenRequest'
510
+ example:
511
+ grant_type: urn:ietf:params:oauth:grant-type:jwt-bearer
512
+ assertion: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
513
+ client_id: my-gateway-client
514
+ application/x-www-form-urlencoded:
515
+ schema:
516
+ $ref: '#/components/schemas/TokenRequest'
517
+ responses:
518
+ '200':
519
+ description: Access token issued successfully.
520
+ headers:
521
+ Cache-Control:
522
+ description: Always `no-cache`.
523
+ schema:
524
+ type: string
525
+ examples:
526
+ - no-cache
527
+ content:
528
+ application/json:
529
+ schema:
530
+ $ref: '#/components/schemas/TokenResponse'
531
+ '400':
532
+ description: |
533
+ Bad Request — the `grant_type` is not `urn:ietf:params:oauth:grant-type:jwt-bearer`,
534
+ the `assertion` field is empty, or required fields are missing.
535
+ content:
536
+ application/json:
537
+ schema:
538
+ $ref: '#/components/schemas/ErrorResponse'
539
+ '401':
540
+ description: |
541
+ Unauthorized — the JWT assertion failed verification (bad signature, wrong issuer/subject,
542
+ expired token, or missing `exp` claim).
543
+ content:
544
+ application/json:
545
+ schema:
546
+ $ref: '#/components/schemas/ErrorResponse'
547
+ '415':
548
+ $ref: '#/components/responses/UnsupportedMediaType'
549
+ '422':
550
+ $ref: '#/components/responses/UnprocessableEntity'
551
+ security: [] # Token endpoint itself is unauthenticated
552
+ tags:
553
+ - Auth
554
+ # ---------------------------------------------------------------------------
555
+ # Prometheus metrics
556
+ # ---------------------------------------------------------------------------
557
+ /metrics:
558
+ get:
559
+ operationId: getMetrics
560
+ summary: Prometheus metrics
561
+ description: |
562
+ Returns Prometheus-format metrics for all bridges managed by this gateway instance.
563
+
564
+ Supports gzip compression: include `Accept-Encoding: gzip` in the request to receive
565
+ a compressed response (the response will include `Content-Encoding: gzip`).
566
+
567
+ This endpoint is only exposed when `prometheus_enabled = true` in `gateway.toml`.
568
+ It can optionally require HTTP Basic authentication (`prometheus_auth = "basic"`).
569
+ parameters:
570
+ - name: Accept-Encoding
571
+ in: header
572
+ description: Set to `gzip` to receive a compressed response.
573
+ required: false
574
+ schema:
575
+ type: string
576
+ examples:
577
+ - gzip
578
+ responses:
579
+ '200':
580
+ description: Prometheus text exposition format (OpenMetrics 0.0.4 compatible).
581
+ headers:
582
+ Content-Encoding:
583
+ description: Present with value `gzip` when compression was requested and
584
+ applied.
585
+ schema:
586
+ type: string
587
+ examples:
588
+ - gzip
589
+ content:
590
+ text/plain:
591
+ schema:
592
+ description: Prometheus text exposition format, version 0.0.4.
593
+ type: string
594
+ examples:
595
+ - |
596
+ # HELP faspio_bridge_sessions_total Total number of sessions
597
+ # TYPE faspio_bridge_sessions_total counter
598
+ faspio_bridge_sessions_total{bridge="Bridge-1"} 42
599
+ '401':
600
+ $ref: '#/components/responses/Unauthorized'
601
+ '500':
602
+ $ref: '#/components/responses/InternalServerError'
603
+ tags:
604
+ - Metrics
605
+ # =============================================================================
606
+ # Components
607
+ # =============================================================================
608
+ components:
609
+ # ---------------------------------------------------------------------------
610
+ # Parameters
611
+ # ---------------------------------------------------------------------------
612
+ parameters:
613
+ BridgeId:
614
+ name: id
615
+ in: path
616
+ required: true
617
+ description: |
618
+ Unique identifier of the bridge. Bridge IDs are assigned by the gateway at creation time
619
+ and are stable for the lifetime of the gateway process.
620
+ schema:
621
+ type: string
622
+ examples:
623
+ - '1'
624
+ # ---------------------------------------------------------------------------
625
+ # Schemas
626
+ # ---------------------------------------------------------------------------
627
+ schemas:
628
+ # ------------------------------------------------------------------
629
+ # Enumerations (extracted from bridge_config.hpp / rest_api.cpp)
630
+ # ------------------------------------------------------------------
631
+
632
+ Protocol:
633
+ description: |
634
+ Transport protocol used on an abutment:
635
+ - `tcp`: Transmission Control Protocol (reliable, ordered byte stream)
636
+ - `udp`: User Datagram Protocol (unreliable, connectionless datagrams)
637
+ - `fasp`: IBM Aspera FASP (reliable high-speed UDP-based transfer protocol)
638
+ type: string
639
+ examples:
640
+ - fasp
641
+ enum:
642
+ - tcp
643
+ - udp
644
+ - fasp
645
+ BridgeSource:
646
+ description: |
647
+ Indicates the origin of a bridge configuration.
648
+
649
+ | Value | Description |
650
+ |-----------|-------------|
651
+ | `static` | Loaded from `gateway.toml` at startup. Read-only via the API — cannot be deleted or updated. |
652
+ | `dynamic` | Created at runtime via `POST /bridges`. Mutable and persisted to the runtime state file. |
653
+ type: string
654
+ examples:
655
+ - dynamic
656
+ enum:
657
+ - static
658
+ - dynamic
659
+ # ------------------------------------------------------------------
660
+ # Port representation
661
+ # ------------------------------------------------------------------
662
+
663
+ PortList:
664
+ description: |
665
+ Expanded list of port numbers (integers) as returned by the API.
666
+ A request range `"2000-2002"` is expanded to `[2000, 2001, 2002]`.
667
+ type: array
668
+ items:
669
+ type: integer
670
+ format: int32
671
+ minimum: 1
672
+ maximum: 65535
673
+ examples:
674
+ - - 2000
675
+ - 2001
676
+ minItems: 1
677
+ PortRange:
678
+ description: |
679
+ Port or port range string as accepted in request bodies.
680
+
681
+ - Single port: `"2000"`
682
+ - Contiguous range: `"2000-2003"` (inclusive, expands to 4 ports)
683
+
684
+ Port numbers must be between 1 and 65535.
685
+ type: string
686
+ examples:
687
+ - 2000-2001
688
+ pattern: ^\d{1,5}(-\d{1,5})?$
689
+ # ------------------------------------------------------------------
690
+ # Abutment schemas (request / response split)
691
+ # ------------------------------------------------------------------
692
+
693
+ LocalAbutmentRequest:
694
+ description: |
695
+ Configuration of the **local** abutment — the side that accepts incoming connections
696
+ on this gateway node.
697
+ type: object
698
+ properties:
699
+ bind_address:
700
+ description: |
701
+ IP address or hostname that the local abutment binds to.
702
+ Use `"0.0.0.0"` to listen on all interfaces.
703
+ type: string
704
+ examples:
705
+ - 127.0.0.1
706
+ port:
707
+ $ref: '#/components/schemas/PortRange'
708
+ protocol:
709
+ description: |
710
+ Protocol accepted on the local side. Typically `tcp` or `udp`.
711
+ example: tcp
712
+ $ref: '#/components/schemas/Protocol'
713
+ tls_enabled:
714
+ description: |
715
+ When `true`, the local abutment expects TLS-wrapped connections.
716
+ Requires `tls_certificate`, `cert_key` (or a combined `cert_chain`) to be
717
+ configured in `gateway.toml`.
718
+ type: boolean
719
+ examples:
720
+ - false
721
+ required:
722
+ - bind_address
723
+ - port
724
+ - protocol
725
+ - tls_enabled
726
+ ForwardAbutmentRequest:
727
+ description: |
728
+ Configuration of the **forward** abutment — the side that establishes outgoing connections
729
+ to the remote gateway peer.
730
+ type: object
731
+ properties:
732
+ host:
733
+ description: |
734
+ One or more hostnames or IP addresses of the remote peer gateway.
735
+ When multiple hosts are specified, the gateway will attempt each in order as a fallback
736
+ (first host is the primary; remaining hosts are used if the primary is unreachable).
737
+ type: array
738
+ items:
739
+ type: string
740
+ examples:
741
+ - - gw2.example.com
742
+ - 10.0.0.2
743
+ minItems: 1
744
+ bind_address:
745
+ description: |
746
+ Optional local IP address to bind the outgoing connection to.
747
+ When omitted, the OS selects the source address automatically.
748
+ type: string
749
+ examples:
750
+ - 192.168.1.10
751
+ port:
752
+ $ref: '#/components/schemas/PortRange'
753
+ protocol:
754
+ description: |
755
+ Protocol used to connect to the remote peer. Typically `fasp` for acceleration.
756
+ example: fasp
757
+ $ref: '#/components/schemas/Protocol'
758
+ tls_enabled:
759
+ description: |
760
+ When `true`, the outgoing connection to the remote peer is TLS-wrapped.
761
+ type: boolean
762
+ examples:
763
+ - false
764
+ required:
765
+ - host
766
+ - port
767
+ - protocol
768
+ - tls_enabled
769
+ LocalAbutmentResponse:
770
+ description: Local abutment as returned by the API (ports expanded to an integer
771
+ array).
772
+ type: object
773
+ properties:
774
+ bind_address:
775
+ type: string
776
+ examples:
777
+ - 127.0.0.1
778
+ port:
779
+ $ref: '#/components/schemas/PortList'
780
+ protocol:
781
+ $ref: '#/components/schemas/Protocol'
782
+ tls_enabled:
783
+ type: boolean
784
+ examples:
785
+ - false
786
+ required:
787
+ - bind_address
788
+ - port
789
+ - protocol
790
+ - tls_enabled
791
+ ForwardAbutmentResponse:
792
+ description: Forward abutment as returned by the API (ports expanded to an
793
+ integer array).
794
+ type: object
795
+ properties:
796
+ bind_address:
797
+ description: Local bind address for the outgoing connection, if configured.
798
+ type: string
799
+ examples:
800
+ - 192.168.1.10
801
+ host:
802
+ description: List of remote peer hostnames / IP addresses.
803
+ type: array
804
+ items:
805
+ type: string
806
+ examples:
807
+ - - gw2.example.com
808
+ - 10.0.0.2
809
+ port:
810
+ $ref: '#/components/schemas/PortList'
811
+ protocol:
812
+ $ref: '#/components/schemas/Protocol'
813
+ tls_enabled:
814
+ type: boolean
815
+ examples:
816
+ - false
817
+ required:
818
+ - host
819
+ - port
820
+ - protocol
821
+ - tls_enabled
822
+ # ------------------------------------------------------------------
823
+ # Bridge schemas
824
+ # ------------------------------------------------------------------
825
+
826
+ BridgeRequest:
827
+ description: |
828
+ Payload for creating a new bridge via `POST /bridges`.
829
+
830
+ The gateway generates the `id` automatically. The `source` field is always set to
831
+ `dynamic` for bridges created via the API.
832
+ type: object
833
+ properties:
834
+ name:
835
+ description: |
836
+ Human-readable label for the bridge. Does not have to be unique,
837
+ but a descriptive name helps with monitoring and troubleshooting.
838
+ type: string
839
+ examples:
840
+ - Bridge-1
841
+ minLength: 1
842
+ local:
843
+ $ref: '#/components/schemas/LocalAbutmentRequest'
844
+ forward:
845
+ $ref: '#/components/schemas/ForwardAbutmentRequest'
846
+ required:
847
+ - name
848
+ - local
849
+ - forward
850
+ BridgeResponse:
851
+ description: Full bridge configuration as returned by `GET /bridges` and `GET
852
+ /bridges/{id}`.
853
+ type: object
854
+ properties:
855
+ id:
856
+ description: |
857
+ Gateway-assigned unique identifier for this bridge.
858
+ Stable for the lifetime of the gateway process.
859
+ type: string
860
+ examples:
861
+ - '1'
862
+ name:
863
+ description: Human-readable label for the bridge.
864
+ type: string
865
+ examples:
866
+ - Bridge-1
867
+ source:
868
+ $ref: '#/components/schemas/BridgeSource'
869
+ local:
870
+ $ref: '#/components/schemas/LocalAbutmentResponse'
871
+ forward:
872
+ $ref: '#/components/schemas/ForwardAbutmentResponse'
873
+ required:
874
+ - id
875
+ - name
876
+ - source
877
+ - local
878
+ - forward
879
+ # ------------------------------------------------------------------
880
+ # OAuth 2.0
881
+ # ------------------------------------------------------------------
882
+
883
+ TokenRequest:
884
+ description: OAuth 2.0 token request body (JWT Bearer grant).
885
+ type: object
886
+ properties:
887
+ grant_type:
888
+ description: |
889
+ Must be `urn:ietf:params:oauth:grant-type:jwt-bearer` (RFC 7523).
890
+ type: string
891
+ examples:
892
+ - urn:ietf:params:oauth:grant-type:jwt-bearer
893
+ const: urn:ietf:params:oauth:grant-type:jwt-bearer
894
+ assertion:
895
+ description: |
896
+ A signed JWT (JWS) assertion issued by the client.
897
+
898
+ The JWT must contain:
899
+ - `iss`: the `client_id` configured in `gateway.toml`
900
+ - `sub`: the `client_id` configured in `gateway.toml`
901
+ - `exp`: a future expiry timestamp
902
+
903
+ The signature must be an RS256 signature verifiable with the public key
904
+ at `jwt_verification_key` in `gateway.toml`.
905
+ type: string
906
+ examples:
907
+ - eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJteS1jbGllbnQiLCJzdWIiOiJteS1jbGllbnQiLCJleHAiOjE3MDAwMDAwMDB9.signature
908
+ client_id:
909
+ description: |
910
+ Optional. The OAuth 2.0 client identifier. When provided, it is validated
911
+ against the `client_id` value in `gateway.toml`. If omitted, the `iss`/`sub`
912
+ claims of the assertion are used for validation.
913
+ type: string
914
+ examples:
915
+ - my-gateway-client
916
+ required:
917
+ - grant_type
918
+ - assertion
919
+ TokenResponse:
920
+ description: Successful OAuth 2.0 token response.
921
+ type: object
922
+ properties:
923
+ access_token:
924
+ description: |
925
+ RS256-signed JWT access token. Include this in the `Authorization: Bearer <token>`
926
+ header for subsequent API calls.
927
+ type: string
928
+ examples:
929
+ - eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
930
+ token_type:
931
+ description: Always `Bearer`.
932
+ type: string
933
+ examples:
934
+ - Bearer
935
+ const: Bearer
936
+ expires_in:
937
+ description: Token lifetime in seconds. Default is 3600 (1 hour).
938
+ type: integer
939
+ format: int64
940
+ examples:
941
+ - 3600
942
+ required:
943
+ - access_token
944
+ - token_type
945
+ - expires_in
946
+ # ------------------------------------------------------------------
947
+ # Error schema
948
+ # ------------------------------------------------------------------
949
+
950
+ ErrorResponse:
951
+ description: |
952
+ Generic error response body. Not all error responses include a body —
953
+ some HTTP status codes (for example, 204, 404) may return no content.
954
+ type: object
955
+ properties:
956
+ message:
957
+ description: Human-readable error description.
958
+ type: string
959
+ examples:
960
+ - bridge not found
961
+ required:
962
+ - message
963
+ # ---------------------------------------------------------------------------
964
+ # Reusable responses
965
+ # ---------------------------------------------------------------------------
966
+ responses:
967
+ BadRequest:
968
+ description: |
969
+ Bad Request — the request could not be parsed or the path parameter is invalid.
970
+ content:
971
+ application/json:
972
+ schema:
973
+ $ref: '#/components/schemas/ErrorResponse'
974
+ example:
975
+ message: invalid bridge id
976
+ Unauthorized:
977
+ description: |
978
+ Unauthorized — no credentials were provided, or the provided credentials are invalid.
979
+
980
+ The response includes a `WWW-Authenticate` header indicating the expected scheme:
981
+ - Basic auth: `WWW-Authenticate: Basic realm="faspio Gateway API", charset="utf-8"`
982
+ - Bearer auth: `WWW-Authenticate: Bearer realm="Bridges", charset="utf-8"`
983
+ headers:
984
+ WWW-Authenticate:
985
+ schema:
986
+ type: string
987
+ example: Basic realm="faspio Gateway API", charset="utf-8"
988
+ content:
989
+ text/plain:
990
+ schema:
991
+ type: string
992
+ example: Unauthorized
993
+ Forbidden:
994
+ description: |
995
+ Forbidden — the operation is not permitted on this resource.
996
+ This is returned when attempting to delete or update a **static** bridge
997
+ (one loaded from `gateway.toml`). Static bridges are immutable via the API.
998
+ content:
999
+ application/json:
1000
+ schema:
1001
+ $ref: '#/components/schemas/ErrorResponse'
1002
+ example:
1003
+ message: cannot delete static bridge via REST API
1004
+ NotFound:
1005
+ description: Not Found — no bridge with the given `id` exists.
1006
+ content:
1007
+ application/json:
1008
+ schema:
1009
+ $ref: '#/components/schemas/ErrorResponse'
1010
+ example:
1011
+ message: bridge not found
1012
+ UnsupportedMediaType:
1013
+ description: |
1014
+ Unsupported Media Type — the `Content-Type` header is missing or not
1015
+ `application/json` (or `application/x-www-form-urlencoded` for the token endpoint).
1016
+ content:
1017
+ application/json:
1018
+ schema:
1019
+ $ref: '#/components/schemas/ErrorResponse'
1020
+ example:
1021
+ message: Content-Type must be application/json
1022
+ UnprocessableEntity:
1023
+ description: |
1024
+ Unprocessable Entity — the request body is syntactically valid JSON but
1025
+ semantically incorrect (for example, a required field is missing, an enum value is
1026
+ unrecognized, or a port range is malformed).
1027
+ content:
1028
+ application/json:
1029
+ schema:
1030
+ $ref: '#/components/schemas/ErrorResponse'
1031
+ example:
1032
+ message: "JSON parse error: [json.exception.out_of_range.403] key 'name' not
1033
+ found"
1034
+ InternalServerError:
1035
+ description: Internal Server Error — an unexpected error occurred in the gateway.
1036
+ content:
1037
+ application/json:
1038
+ schema:
1039
+ $ref: '#/components/schemas/ErrorResponse'
1040
+ example:
1041
+ message: unexpected error creating bridge
1042
+ # ---------------------------------------------------------------------------
1043
+ # Security schemes
1044
+ # ---------------------------------------------------------------------------
1045
+ securitySchemes:
1046
+ basicAuth:
1047
+ type: http
1048
+ scheme: basic
1049
+ description: |
1050
+ HTTP Basic Authentication. The password is stored as a SHA-512 or PBKDF2 digest
1051
+ in `gateway.toml` under `[admin.basic_auth]`. Configure with:
1052
+ ```toml
1053
+ [admin]
1054
+ rest_api_auth = "basic"
1055
+ [admin.basic_auth]
1056
+ username = "admin"
1057
+ password_digest = "<sha512-or-pbkdf2-hash>"
1058
+ ```
1059
+ bearerAuth:
1060
+ type: http
1061
+ scheme: bearer
1062
+ bearerFormat: JWT
1063
+ description: |
1064
+ OAuth 2.0 Bearer token (RS256-signed JWT). Obtain a token from `POST /auth/token`
1065
+ using the JWT Bearer grant type. Configure the gateway with:
1066
+ ```toml
1067
+ [admin]
1068
+ rest_api_auth = "oauth2"
1069
+ [admin.oauth2]
1070
+ client_id = "my-gateway-client"
1071
+ jwt_grant_enabled = true
1072
+ jwt_verification_key = "/etc/faspio-gateway/client_public.pem"
1073
+ jwt_signing_key = "/etc/faspio-gateway/server_private.pem"
1074
+ ```
1075
+ tags:
1076
+ - name: Health
1077
+ description: Liveness probe — verify that the gateway process is reachable.
1078
+ - name: Bridges
1079
+ description: |
1080
+ Create and manage network bridges.
1081
+ A **bridge** is a bidirectional pipe that accepts connections on a local abutment (TCP or UDP)
1082
+ and forwards them to a remote peer via a forward abutment (FASP, TCP, or UDP).
1083
+ - name: Auth
1084
+ description: |
1085
+ OAuth 2.0 token endpoint. Only available when `rest_api_auth = "oauth2"` is set in `gateway.toml`.
1086
+ Uses the JWT Bearer grant type (`urn:ietf:params:oauth:grant-type:jwt-bearer`).
1087
+ - name: Metrics
1088
+ description: |
1089
+ Prometheus-compatible metrics endpoint. Only available when `prometheus_enabled = true`
1090
+ in `gateway.toml`. Supports gzip compression via `Accept-Encoding: gzip`.
1091
+ externalDocs:
1092
+ description: IBM Aspera faspio Gateway — Official Documentation
1093
+ url: https://www.ibm.com/docs/en/faspio-gateway
1094
+ security:
1095
+ - basicAuth: []
1096
+ - bearerAuth: []
1097
+ - {}