OpenAPI Gateway Annotations
This page explains how Alpha Looms services can generate custom OpenAPI x-* extensions that describe intended API gateway exposure, public access, required permissions, and branch-header requirements.
These annotations are available in both the shared Quarkus and NestJS common packages. They enrich the generated OpenAPI contract so consumers, reviewers, and portal tooling can understand how a route is intended to be exposed through the platform gateway layer.
What These Extensions Describe
The shared annotations generate operation-level OpenAPI extensions such as:
x-expose-to-gatewaysx-public-accessx-required-permissionsx-attach-branch-headersx-zudoku-badges
For protected routes, required permissions may also be appended to the operation description as a Markdown section.
These fields are contract metadata. They describe intended route exposure and access expectations, but they are not the runtime enforcement mechanism by themselves.
How This Relates To API Gateway
Alpha Looms currently uses gateway slugs such as:
admin-apigwborrower-apigwopenapi-apigw
When a route emits x-expose-to-gateways, it declares which gateway surface that operation is intended to appear behind. Combined with the other extensions, this makes it easier to distinguish:
- public versus protected operations
- gateway-specific exposure targets
- permission requirements for protected routes
- whether branch headers are expected
This metadata is especially useful when reviewing generated OpenAPI output, publishing entries in the API Catalog, or validating that a service is documenting route exposure consistently.
Quarkus
Use the shared annotations from mn.and.common.openapi.annotation to add custom x-* extensions to generated operations.
These annotations may be placed on a resource class or an individual route method. Method-level annotations override controller-level values. The library matches routes primarily by path plus HTTP method, with an operation-id fallback for compatibility.
Supported annotations
@ExposeToApiGatewayswritesx-expose-to-gatewaysusing one or moreApiGatewayenum values.@PublicAccesswritesx-public-access: true.@RequiredPermissionswritesx-required-permissionswith one or more permission strings.@AttachBranchHeaderswritesx-attach-branch-headers: true.
The library also derives x-zudoku-badges for Zudoku-friendly operation badges. It adds access badges first (Public access or Protected), then Branch headers, then one gray badge per gateway.
For non-public operations, required permissions are also appended to the operation description as a Markdown section. When @PublicAccess is present, the library suppresses x-required-permissions, x-attach-branch-headers, and their related badges and description output.
Default exposed gateways
If @ExposeToApiGateways is present without explicit values, the library uses mn.and.openapi.default-expose-to-gateways from application.properties.
Leave the property empty to emit nothing by default.
Code
Example
Code
This produces operation extensions such as x-expose-to-gateways, x-public-access, x-required-permissions, x-attach-branch-headers, and x-zudoku-badges in /q/openapi.
Public operations still get gateway badges, but they suppress x-required-permissions, x-attach-branch-headers, and permission details in the description when @PublicAccess is present.
NestJS
Use the OpenAPI helpers exported from @and/nest-common to add route metadata and transform the generated Swagger document.
These decorators and helpers allow downstream NestJS services to emit the same shared x-* extensions used by the Quarkus implementation.
Supported decorators and helpers
@ExposeToGateways()@PublicAccess()@RequiredPermissions()@AttachBranchHeaders()transformOpenApiDocument()
If your application already uses setupApplication() from @and/nest-common, you usually do not need to call transformOpenApiDocument() yourself because setupApplication() already applies it.
Required setup
Import the shared decorators and transformer:
Code
Ensure DiscoveryModule is available so the transformer can map controller methods back into generated OpenAPI operations.
Code
Default exposed gateways
If @ExposeToGateways() is called with no arguments, the default gateway list is resolved from ConfigService key OPENAPI_DEFAULT_EXPOSE_TO_GATEWAYS.
Code
Supported shared gateway values are:
ApiGateway.Admin->admin-apigwApiGateway.Borrower->borrower-apigwApiGateway.OpenAPI->openapi-apigw
If config is missing or empty, the fallback is all supported gateways.
Example controller
Code
Applying the transformer
Two supported integration styles are common.
Use setupApplication() if your service already relies on the shared application bootstrap:
Code
Or apply the transformer manually after SwaggerModule.createDocument():
Code
The generated Swagger document can then expose fields such as x-expose-to-gateways, x-public-access, x-required-permissions, x-attach-branch-headers, and x-zudoku-badges.
Resolution Rules
Both implementations follow the same practical resolution model:
- method-level gateways override controller or class-level gateways
- method-level permissions override controller or class-level permissions
- public access is OR logic across controller and method
- branch headers are OR logic across controller and method
- public routes suppress permission and branch-header output
- public routes still keep gateway output
If @PublicAccess is combined with permission or branch-header annotations, public access wins. The route still emits gateway metadata, but permission and branch-header metadata are suppressed.
How To Verify
For Quarkus services:
- Start the service.
- Open
/q/openapi. - Inspect an operation and confirm the expected
x-*fields are present.
For NestJS services:
- Start the service.
- Open the generated Swagger JSON, YAML, or Swagger UI.
- Confirm extensions are visible on the operation.
- If using Swagger UI, enable
showExtensions: true.
Typical protected output may look like:
Code
Typical public output may look like:
Code
Troubleshooting
I do not see any x-* fields
Check that the annotations or decorators are actually applied to the controller or route you are inspecting.
For Quarkus, verify you are looking at the generated /q/openapi output after the shared extension library has run.
For NestJS, verify that you are using setupApplication() or explicitly calling transformOpenApiDocument().
Swagger UI does not show the extensions
Swagger UI may hide custom fields unless extension display is enabled.
For NestJS manual setup, enable:
Code
@ExposeToGateways() with no arguments is not using the expected defaults
For Quarkus, verify mn.and.openapi.default-expose-to-gateways is set in application.properties and contains valid gateway slugs.
For NestJS, verify:
ConfigModuleis configured- the key name is exactly
OPENAPI_DEFAULT_EXPOSE_TO_GATEWAYS - the configured values are valid gateway slugs
Public routes are not showing permissions or branch-header metadata
This is expected behavior.
When a route is marked public, permission and branch-header metadata are suppressed even if those annotations or decorators are also present.
openapi.yaml is not created during nest build
This is also expected when using setupApplication().
openapi.yaml is generated when the app starts and the Swagger setup runs. It is not generated by nest build alone.