7. API contract and reference¶
The C-PAT API is defined by one OpenAPI document, api/specification/C-PAT.yaml. It is the reference for every operation, and it is also the router: the API resolves handlers from it at startup and validates every request against it. This page tells you where to read it, how to try it, and the conventions to follow when you change it.
7.1. The contract¶
Format: OpenAPI 3.1 (
openapi: 3.1.2as of 1.4.4).Size: 76 path items and 182 operations as of 1.4.4.
Boot-time patches:
getOAS()inapi/bootstrap/docs.jssetsinfo.versionfrompackage.json, theserversURLs fromCPAT_SWAGGER_SERVERandCPAT_ALTERNATE_SWAGGER_SERVER, and theopenIdConnectUrlof theoauthsecurity scheme fromCPAT_OIDC_PROVIDER. The file in the repository leaves those three values empty on purpose.Runtime access:
GET /api/op/definitionreturns the patched document. The optionaljsonpathquery parameter (components.parameters.JsonPathQuery) filters it with a JSONPath expression; the container health probe uses$.info.version.
7.2. Browse and try the API¶
Set CPAT_SWAGGER_ENABLED=true and the API serves Swagger UI at /api-docs. Its Authorize button runs the authorization code flow with PKCE against the configured provider and returns to CPAT_SWAGGER_REDIRECT (http://localhost:8086/api-docs/oauth2-redirect.html by default), so that URL must be a valid redirect URI of the c-pat client in your realm. With Swagger enabled, /swagger.json and /openapi.json return the patched document without authentication; leave Swagger disabled in deployments that must not expose the contract.
Lint the contract before every change and after it:
cd api
npm run lint:spec
The script runs Redocly with the recommended ruleset. The PR Tests workflow runs the same command.
7.3. Security¶
Every operation declares the oauth security scheme with one scope: c-pat:read for reads, c-pat:write for writes, and c-pat:op for operational and administrative endpoints. The API’s scope handler (validateOauthSecurity in api/utils/auth.js) reads the token’s scope claim and matches by prefix, so a token holding c-pat satisfies c-pat:read, and CPAT_SCOPE_PREFIX is prepended to every required scope when a provider namespaces them. A request without a token receives 401; a token without the scope receives 403. See Scopes, and Privileges for the provider configuration.
Scopes gate operations; access level gates data. After the scope check, the service confirms the caller’s level in the collection that owns the data. Administrative operations also take the elevate query parameter, declared once as components.parameters.ElevateQuery (elevate, boolean, default false) and referenced with $ref. See Backend guide.
7.4. Conventions for operations¶
Check each item when you add or change an operation. The resolver and the validator depend on the first four.
operationIdis unique and equals the name of the exported handler function.The first entry of
tagsequals the controller file name underapi/Controllers/, case-sensitive.securitylists theoauthscheme with exactly one scope.Path and query parameters are declared in full; the validator rejects undeclared query parameters.
Reuse the shared parameters:
ElevateQuery,collectionIdPath, andJsonPathQueryundercomponents.parameters.Responses declare
200(or201for a creation),400wherever input can be invalid,403through$ref: '#/components/responses/forbidden'where an access level applies,404where a resource is looked up, and alwaysdefault: $ref: '#/components/responses/unexpectedError'.Schemas provide
examplesas an array rather than a singleexample.Binary request bodies use
contentMediaTypein the schema rather thanformat: binary.Multipart upload operations carry
x-eov-file-handler: true. The marker documents that the handler readsreq.files; the validator does not act on it.Tenable proxy operations reuse
components.responses.tenableUpstreamError(502) andcomponents.responses.tenableUnavailable(503).
7.5. Validation behaviour¶
The validator is configured in api/bootstrap/middlewares.js:
Request validation is on, with
allowUnknownQueryParameters: falseandcoerceTypes: false. An undeclared query parameter or a string where the contract says integer is a 400.The contract itself is validated at startup (
validateApiSpec: true); a malformed document stops the API.Response validation is off by default. Set
CPAT_DEV_RESPONSE_VALIDATION=logOnlyin development and the validator logs a('rest', 'responseValidation')record for every response that does not match its schema, without failing the request.
7.6. Error body¶
Handlers answer errors through sendError with { "error": <message>, "detail": <detail> } and the status code of the error class. Errors raised before a handler runs, including validation failures, reach the terminal error middleware and are answered as { "error", "code", "detail" }, with a stack field added for status 500. The error schema in components.schemas describes the shape. The status codes and messages are listed in Backend guide.
7.7. Version policy¶
The contract stays on OpenAPI 3.1.x. express-openapi-validator does not accept 3.2 documents, and the API validates the contract at startup, so a bump to 3.2 stops the API from starting.
7.8. Tenable proxy operations¶
Operation |
|
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Each forwards to the corresponding path under /rest on the configured Tenable.sc server with the deployment’s API keys. The saved-filter operations under /tenableFilters and /tenableFilter are ordinary C-PAT operations, not proxies. See Backend guide for the proxy’s behaviour.