diff --git a/code/API_definitions/CAMARA-subscriptions-openapi.yaml b/code/API_definitions/CAMARA-subscriptions-openapi.yaml index 304fed0..d151a20 100644 --- a/code/API_definitions/CAMARA-subscriptions-openapi.yaml +++ b/code/API_definitions/CAMARA-subscriptions-openapi.yaml @@ -1,3 +1,4 @@ +--- openapi: 3.0.3 info: title: Extended CloudEvents Subscriptions API for CAMARA @@ -15,7 +16,8 @@ info: - `config.subscriptionStartTime`: optional timestamp (ISO 8601) to include past events - (optional) `config.cacheResyncRequest`: `true` to request current state resync - (optional) `config.eventResyncRequest`: `true` + `config.eventResyncTime` to request historical backlog - • Server responds **201 Created** with subscription metadata. + + Server responds **201 Created** with subscription metadata. 2. **Cache state delivery** *(if `cacheResyncRequest=true`)* Immediately pushes snapshot of **current state event** of subscribed event 'type'. This snapshot reflects the relevant latest known state of the 'type' of the subscription. @@ -37,53 +39,132 @@ info: - **Idempotency**: each CloudEvent `id` is unique; consumers must dedupe. - **Acknowledgement**: HTTP 2xx confirms receipt; failures trigger retries. + 6. **Notification polcies** + + - What does `periodicity` mean? + The `periodicity` field allows an API consumer to request **scheduled (periodic) event deliveries** + instead of relying on continuous or ad-hoc triggers. + Its value is an [ISO-8601 duration](https://en.wikipedia.org/wiki/ISO_8601#Durations) + (for example, `PT1H` = every 1 hour, `PT15M` = every 15 minutes, `P1D` = once per day). + + - How does the server interpret `periodicity`? + When 'periodicity` is provided, the Subscription Manager creates a **scheduler** for that subscription: + - The first tick occurs at `startsAt` (or the next alignment boundary ≥ now if `alignment` is given). + - Subsequent ticks occur every *periodicity* interval until `expiresAt` or explicit `DELETE`. + - At each tick, the server generates a CloudEvent for the configured `eventMode`: + - `snapshot`: full current dataset (even if unchanged) + - `changes`: only if a change occurred since the previous tick + - `digest`: aggregated metrics over the interval defined by `window` (defaults to `periodicity`) + - The CloudEvent `time` attribute reflects the scheduled tick instant. + - The CloudEvent `id` should be unique and stable for that tick, + for example `":"`, so that replays can be deduplicated. + + - How does alignment work with periodicity? + The optional `alignment` timestamp anchors the schedule to a wall-clock boundary. + For instance, with `periodicity: PT1H` and `alignment: 2025-10-29T12:00:00Z`, + events are delivered at 12:00, 13:00, 14:00, and so on. + + - What if no change occurs during a tick? + - For `eventMode: snapshot`, the server still emits a CloudEvent snapshot. + - For `eventMode: changes`, the server MAY suppress emission, + or MAY send a minimal heartbeat event with `data.noChange: true`. + - For `eventMode: digest`, the server emits aggregated statistics regardless of change. + + - How does this interact with subscription lifecycle? + - `ACTIVE` subscriptions continue periodic emission until `expiresAt` or `DELETE`. + - When the scheduler reaches `expiresAt`, the subscription status transitions to `EXPIRED`. + - Manual suspension (`PATCH` to `INACTIVE`) pauses the scheduler. + - Manual deletion (`DELETE`) terminates the schedule permanently. + + - What if `periodicity` is omitted? + The subscription behaves as a **pure event-driven (triggered) subscription**, + generating events immediately upon relevant state changes, with no scheduling. + + - Can multiple periodicities be requested in one subscription? + No. Each subscription has exactly one cadence. + To obtain data at different cadences (e.g., hourly and daily), + create separate subscriptions with distinct `periodicity` values. + + - How is reliability handled for periodic emissions? + Each generated CloudEvent follows the same delivery guarantees + (retry policy, `data.syncStatus`, and backoff settings) + as other events defined in the CAMARA Event Subscription and Notification Guide. + + 7. **Enforce service-specific, fine-grained entitlements** + + - Use CloudEvents only to carry event data; security is enforced before events are created or delivered. The CloudEvents AuthContext extension + (https://github.com/cloudevents/spec/blob/main/cloudevents/extensions/authcontext.md) is explicitly informational, not a security mechanism. + + - Document service-specific requirements in vendor extension (x-camara-entitlements) inside each service's pathless YAML; let your gateway/service read these at runtime or in CI. + + - For truly fine-grained grants (specific event types, filters, regions, device sets), use OAuth 2.0 Rich Authorization Requests (RAR) and/or Resource Indicators avoiding scope explosion. + + - Authorization layer (IdP + gateway/service): + + At authorization time: the client requests access using RAR authorization_details describing the subscription they want (service, event types, filters). The Authorization (Auth) Server + issues a token embedding these details (or a reference), plus coarse scope(s). + + At subscription creation time: the POST /subscriptions handler: + + - Parses the request (eventTypes, filters, target service). + + - Loads the service's x-camara-entitlements (from the service YAML or a prebuilt registry). + + - Verifies the caller's token: + + - Has the coarse scope (events:subscribe)? + + - Matches RAR details (event types, filters, service)? + + - Satisfies any roles/claims declared for those event types in x-camara-entitlements? + Optionally bind tokens to a resource indicator so a token is issued for a specific service domain (e.g., resource=urn:camara:connected-network-type) to keep cross-service abuse in check. license: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0.html version: wip - x-camara-commonalities: 0.6.0 - + x-camara-commonalities: tbd tags: - - name: CAMARA Extended CloudEvents Common Subscription - description: Operations to manage subscriptions for receiving notifications on CAMARA common cloud events. - + - name: CAMARA Extended CloudEvents Subscription + description: Operations to manage subscriptions for receiving notifications on + CAMARA CloudEvents. servers: - - url: "{apiRoot}" + - url: '{apiRoot}' variables: apiRoot: default: http://localhost:9091 - description: API root, defined by the service provider, e.g. api.example.com or api.example.com/somepath - + description: API root, defined by the service provider, e.g. api.example.com + or api.example.com/somepath paths: /subscriptions: post: - tags: - - CAMARA Extended CloudEvents Common Subscription - summary: "Create a subscription for receiving notifications on the common CAMARA CloudEvents." - description: Create a subscription for receiving notifications on the common CAMARA CloudEvents. + tags: [CAMARA Extended CloudEvents Subscription] + summary: Create a CAMARA CloudEvents subscription for receiving callbacks + description: | + Create a CAMARA CloudEvents subscription for receiving callbacks. + Implementations SHOULD perform CloudEvents HTTP WebHook validation before first delivery and MAY return 202 Accepted with status=ACTIVATION_REQUESTED until validation completes. operationId: createCamaraCloudEventsSubscription parameters: - - $ref: "#/components/parameters/x-correlator" + - $ref: '#/components/parameters/x-correlator' security: - openId: - - camara-cloudevents-subscriptions:org.camaraproject.camara-cloudevents-subscriptions.v0.common:create + - camara-cloudevents-subscriptions:org.camaraproject.camara-cloudevents-subscriptions.v0.common:create # coarse scope only requestBody: required: true content: application/json: schema: - $ref: "#/components/schemas/CamaraExtendedSubscriptionRequest" + $ref: '#/components/schemas/CamaraExtendedSubscriptionRequest' callbacks: notifications: - "{$request.body#/sink}": + '{$request.body#/sink}': post: - summary: "notifications callback" + summary: CAMARA CloudEvents notifications callback description: | Important: this endpoint is to be implemented by the API consumer. The CAMARA Cloud Events server will call this endpoint whenever the common CAMARA CloudEvents. operationId: postCamaraCloudEventsNotification parameters: - - $ref: "#/components/parameters/x-correlator" + - $ref: '#/components/parameters/x-correlator' requestBody: required: true content: @@ -91,74 +172,149 @@ paths: schema: type: array items: - $ref: "#/components/schemas/CamaraExtendedCloudEventsAttribute" + $ref: '#/components/schemas/CamaraExtendedCloudEventsAttribute' responses: - "204": + '204': description: Successful notification headers: x-correlator: - $ref: "#/components/headers/x-correlator" - "400": - $ref: "#/components/responses/Generic400" - "401": - $ref: "#/components/responses/Generic401" - "403": - $ref: "#/components/responses/Generic403" - "410": - $ref: "#/components/responses/Generic410" - "429": - $ref: "#/components/responses/Generic429" + $ref: '#/components/headers/x-correlator' + '400': + $ref: '#/components/responses/Generic400' + '401': + $ref: '#/components/responses/Generic401' + '403': + $ref: '#/components/responses/Generic403' + '410': + $ref: '#/components/responses/Generic410' + '429': + $ref: '#/components/responses/Generic429' + security: + - notificationsBearerAuth: [] + webhookValidation: + '{$request.body#/sink}': + options: + summary: CAMARA CloudEvents HTTP WebHook validation callback + operationId: optionsCamaraCloudEventsWebhookValidation + parameters: + - $ref: '#/components/parameters/x-correlator' + - in: header + name: WebHook-Request-Origin + required: true + schema: {type: string} + description: Origin of the WebHook sender per CloudEvents HTTP WebHook + 1.0.x. + responses: + '200': + description: Sink allows delivery from this origin. + headers: + x-correlator: + $ref: '#/components/headers/x-correlator' + WebHook-Allowed-Origin: + schema: {type: string} + description: Echo of the approved origin. + '403': + $ref: '#/components/responses/Generic403' + subscriptionLifecycle: + '{$request.body#/sink}': + post: + summary: CAMARA CloudEvents subscription lifecycle callback + description: > + One CloudEvents 'type' with three payload formats, distinguished by + 'datacontenttype': + - application/json-patch+json: data is a JSON Patch (RFC 6902) array + - application/merge-patch+json: data is a JSON Merge Patch (RFC 7396) + document + - application/json: data is a full {previous,current} snapshot + operationId: postCamaraCloudEventsSubscriptionLifecycleNotification + parameters: + - $ref: '#/components/parameters/x-correlator' + requestBody: + required: true + content: + application/cloudevents+json: + schema: + oneOf: + - $ref: '#/components/schemas/CamaraConfigChangeEventJsonPatch' + - $ref: '#/components/schemas/CamaraConfigChangeEventMergePatch' + - $ref: '#/components/schemas/CamaraConfigChangeEventSnapshot' + discriminator: + propertyName: datacontenttype + mapping: + application/json-patch+json: '#/components/schemas/CamaraConfigChangeEventJsonPatch' + application/merge-patch+json: '#/components/schemas/CamaraConfigChangeEventMergePatch' + application/json: '#/components/schemas/CamaraConfigChangeEventSnapshot' + responses: + '204': + description: Successful lifecycle notification + headers: + x-correlator: + $ref: '#/components/headers/x-correlator' + '400': + $ref: '#/components/responses/Generic400' + '401': + $ref: '#/components/responses/Generic401' + '403': + $ref: '#/components/responses/Generic403' + '410': + $ref: '#/components/responses/Generic410' + '429': + $ref: '#/components/responses/Generic429' security: - notificationsBearerAuth: [] responses: - "201": - description: Created (Successful creation of subscription) + '201': + description: Created (Successful creation of subscription) and validation + not required or already satisfied. headers: x-correlator: - $ref: "#/components/headers/x-correlator" + $ref: '#/components/headers/x-correlator' + ETag: + $ref: '#/components/headers/ETag' + Accept-Patch: + $ref: '#/components/headers/Accept-Patch' content: application/json: schema: - $ref: "#/components/schemas/CamaraExtendedSubscription" - "202": - description: Request accepted to be processed. It applies for async creation process. + $ref: '#/components/schemas/CamaraExtendedSubscription' + '202': + description: Request accepted to be processed. It applies for async creation + process. When subscription created, validation handshake is pending per + CloudEvents HTTP WebHook. headers: x-correlator: - $ref: "#/components/headers/x-correlator" + $ref: '#/components/headers/x-correlator' content: application/json: schema: - $ref: "#/components/schemas/SubscriptionAsync" - "400": - $ref: "#/components/responses/CreateSubscriptionBadRequest400" - "401": - $ref: "#/components/responses/Generic401" - "403": - $ref: "#/components/responses/SubscriptionPermissionDenied403" - "409": - $ref: "#/components/responses/Generic409" - "422": - $ref: "#/components/responses/CreateSubscriptionUnprocessableEntity422" - "429": - $ref: "#/components/responses/Generic429" - + $ref: '#/components/schemas/SubscriptionAsync' + '400': + $ref: '#/components/responses/CreateSubscriptionBadRequest400' + '401': + $ref: '#/components/responses/Generic401' + '403': + $ref: '#/components/responses/SubscriptionPermissionDenied403' + '409': + $ref: '#/components/responses/Generic409' + '422': + $ref: '#/components/responses/CreateSubscriptionUnprocessableEntity422' + '429': + $ref: '#/components/responses/Generic429' get: - tags: - - CAMARA Extended CloudEvents Common Subscription - summary: "Retrieve a list of CAMARA CloudEvents subscription" + tags: [CAMARA Extended CloudEvents Subscription] + summary: Retrieve CAMARA CloudEvents subscriptions description: Retrieve a list of CAMARA CloudEvents subscription(s) operationId: retrieveCamaraCloudEventsSubscriptionList parameters: - - $ref: "#/components/parameters/x-correlator" + - $ref: '#/components/parameters/x-correlator' security: - - openId: - - camara-cloudevents-subscriptions:read + - openId: [camara-cloudevents-subscriptions:read] responses: - "200": + '200': description: List of event subscription details headers: x-correlator: - $ref: "#/components/headers/x-correlator" + $ref: '#/components/headers/x-correlator' content: application/json: schema: @@ -166,207 +322,287 @@ paths: minItems: 0 items: $ref: '#/components/schemas/CamaraExtendedSubscription' - "400": - $ref: "#/components/responses/Generic400" - "401": - $ref: "#/components/responses/Generic401" - "403": - $ref: "#/components/responses/Generic403" - + '400': + $ref: '#/components/responses/Generic400' + '401': + $ref: '#/components/responses/Generic401' + '403': + $ref: '#/components/responses/Generic403' options: - tags: - - CAMARA Extended CloudEvents Common Subscription - operationId: getCamaraCloudEventsFeatures - summary: getFeatures + tags: [CAMARA Extended CloudEvents Subscription] + summary: Discover CAMARA CloudEvents subscriptions features description: Discover supported features and methods for this endpoint + operationId: getCamaraCloudEventsFeatures parameters: - - $ref: "#/components/parameters/x-correlator" + - $ref: '#/components/parameters/x-correlator' security: - - openId: - - camara-cloudevents-subscriptions:read + - openId: [camara-cloudevents-subscriptions:read] responses: - "200": + '200': description: OK headers: Allow: schema: type: string - default: "GET,POST,OPTIONS" + default: GET,POST,OPTIONS x-correlator: - $ref: "#/components/headers/x-correlator" - "400": - $ref: "#/components/responses/Generic400" - + $ref: '#/components/headers/x-correlator' + '400': + $ref: '#/components/responses/Generic400' /subscriptions/{id}: get: - tags: - - CAMARA Extended CloudEvents Common Subscription - summary: "Retrieve a CAMARA CloudEvents subscription metadata" - description: retrieve CAMARA CloudEvents subscription metadata. + tags: [CAMARA Extended CloudEvents Subscription] + summary: Retrieve a CAMARA CloudEvents subscription + description: retrieve CAMARA CloudEvents subscription. operationId: retrieveCamaraCloudEventsSubscription security: - - openId: - - camara-cloudevents-subscriptions:read + - openId: [camara-cloudevents-subscriptions:read] parameters: - - $ref: "#/components/parameters/x-correlator" - - $ref: "#/components/parameters/SubscriptionId" - - $ref: "#/components/parameters/If-None-Match" - - $ref: "#/components/parameters/If-Modified-Since" + - $ref: '#/components/parameters/x-correlator' + - $ref: '#/components/parameters/SubscriptionId' + - $ref: '#/components/parameters/If-None-Match' + - $ref: '#/components/parameters/If-Modified-Since' responses: - "200": + '200': description: | Subscription metadata. headers: x-correlator: - $ref: "#/components/headers/x-correlator" + $ref: '#/components/headers/x-correlator' ETag: $ref: '#/components/headers/ETag' Cache-Control: $ref: '#/components/headers/Cache-Control' Last-Modified: $ref: '#/components/headers/Last-Modified' + Accept-Patch: + $ref: '#/components/headers/Accept-Patch' content: application/json: schema: - $ref: "#/components/schemas/CamaraExtendedSubscription" - "400": - $ref: "#/components/responses/SubscriptionIdRequired400" - "401": - $ref: "#/components/responses/Generic401" - "403": - $ref: "#/components/responses/Generic403" - "404": - $ref: "#/components/responses/Generic404" - "409": - $ref: "#/components/responses/Generic409" - + $ref: '#/components/schemas/CamaraExtendedSubscription' + '304': + $ref: '#/components/responses/Generic304' + '400': + $ref: '#/components/responses/SubscriptionIdRequired400' + '401': + $ref: '#/components/responses/Generic401' + '403': + $ref: '#/components/responses/Generic403' + '404': + $ref: '#/components/responses/Generic404' + '409': + $ref: '#/components/responses/Generic409' put: - tags: - - CAMARA Extended CloudEvents Common Subscription + tags: [CAMARA Extended CloudEvents Subscription] operationId: updateCamaraCloudEventsSubscription - summary: updateCamaraCloudEventsSubscription - description: Update a CAMARA CloudEvents subscription + summary: Update CAMARA CloudEvents subscription + description: > + Update a CAMARA CloudEvents subscription (full update). The request body MUST + contain a full Subscription representation. + Enforce 422 for forbidden transitions; 412 for ETag mismatches; 409 for already-final + states. If status: "EXPIRED" is, then sends 422. security: - - openId: - - camara-cloudevents-subscriptions:update + - openId: [camara-cloudevents-subscriptions:put] parameters: - - $ref: "#/components/parameters/SubscriptionId" - - $ref: "#/components/parameters/x-correlator" + - $ref: '#/components/parameters/SubscriptionId' + - $ref: '#/components/parameters/x-correlator' + - $ref: '#/components/parameters/If-Match' requestBody: required: true content: application/json: schema: - $ref: "#/components/schemas/CamaraExtendedSubscription" + $ref: '#/components/schemas/CamaraExtendedSubscriptionMergePatch' responses: - "200": + '200': description: OK + headers: + ETag: + $ref: '#/components/headers/ETag' content: application/json: schema: - $ref: "#/components/schemas/CamaraExtendedSubscription" - "400": - $ref: "#/components/responses/CreateSubscriptionBadRequest400" - "404": - $ref: "#/components/responses/Generic404" - + $ref: '#/components/schemas/CamaraExtendedSubscription' + '204': + description: Updated, no content + headers: + x-correlator: + $ref: '#/components/headers/x-correlator' + '400': + $ref: '#/components/responses/CreateSubscriptionBadRequest400' + '404': + $ref: '#/components/responses/Generic404' + '409': + $ref: '#/components/responses/Generic409' + '412': + $ref: '#/components/responses/Generic412' + '422': + $ref: '#/components/responses/CreateSubscriptionUnprocessableEntity422' + patch: + tags: [CAMARA Extended CloudEvents Subscription] + operationId: patchCamaraCloudEventsSubscription + summary: Partially modify CAMARA CloudEvents subscription + description: > + Apply partial modifications using JSON Merge Patch (RFC 7396) using application/merge-patch+json + or JSON Patch (RFC 6902) using application/json-patch+json. + The PATCH shape follows the HTTP/PATCH spec (RFC 5789), supports both Merge + Patch (RFC 7396) and JSON Patch (RFC 6902), and advertises formats via the + Accept-Patch response header. + Enforce 422 for forbidden transitions; 412 for ETag mismatches; 409 for already-final + states. If status: "EXPIRED" is, then sends 422. + security: + - openId: [camara-cloudevents-subscriptions:patch] + parameters: + - $ref: '#/components/parameters/SubscriptionId' + - $ref: '#/components/parameters/x-correlator' + - $ref: '#/components/parameters/If-Match' + requestBody: + required: true + content: + application/merge-patch+json: + schema: + $ref: '#/components/schemas/CamaraExtendedSubscriptionMergePatch' + application/json-patch+json: + schema: + type: array + items: + $ref: '#/components/schemas/CamaraExtendedJsonPatchOperation' + examples: + pauseSubscription: + summary: Set status via JSON Patch + value: + - op: replace + path: /status + value: INACTIVE + resumeSubscription: + summary: Resume via JSON Patch + value: + - op: replace + path: /status + value: ACTIVE + responses: + '200': + description: OK + headers: + ETag: + $ref: '#/components/headers/ETag' + content: + application/json: + schema: + $ref: '#/components/schemas/CamaraExtendedSubscription' + '204': + description: Updated, no content + headers: + x-correlator: + $ref: '#/components/headers/x-correlator' + '400': + $ref: '#/components/responses/CreateSubscriptionBadRequest400' + '404': + $ref: '#/components/responses/Generic404' + '409': + $ref: '#/components/responses/Generic409' + '412': + $ref: '#/components/responses/Generic412' + '415': + $ref: '#/components/responses/Generic415' + '422': + $ref: '#/components/responses/CreateSubscriptionUnprocessableEntity422' delete: - tags: - - CAMARA Extended CloudEvents Common Subscription - summary: "Delete CamaraCloudEvents subscription" + tags: [CAMARA Extended CloudEvents Subscription] + summary: Delete CAMARA CloudEvents subscription operationId: deleteCamaraCloudEventsSubscription description: delete a given CAMARA CloudEvents subscription. security: - - openId: - - camara-cloudevents-subscriptions:delete + - openId: [camara-cloudevents-subscriptions:delete] parameters: - - $ref: "#/components/parameters/SubscriptionId" - - $ref: "#/components/parameters/x-correlator" + - $ref: '#/components/parameters/SubscriptionId' + - $ref: '#/components/parameters/x-correlator' responses: - "204": + '204': description: CAMARA CloudEvents subscription deleted headers: x-correlator: - $ref: "#/components/headers/x-correlator" - "202": - description: Request accepted to be processed. It applies for async deletion process. + $ref: '#/components/headers/x-correlator' + '202': + description: Request accepted to be processed. It applies for async deletion + process. headers: x-correlator: - $ref: "#/components/headers/x-correlator" + $ref: '#/components/headers/x-correlator' content: application/json: schema: - $ref: "#/components/schemas/SubscriptionAsync" - "400": - $ref: "#/components/responses/SubscriptionIdRequired400" - "401": - $ref: "#/components/responses/Generic401" - "403": - $ref: "#/components/responses/Generic403" - "404": - $ref: "#/components/responses/Generic404" - + $ref: '#/components/schemas/SubscriptionAsync' + '400': + $ref: '#/components/responses/SubscriptionIdRequired400' + '401': + $ref: '#/components/responses/Generic401' + '403': + $ref: '#/components/responses/Generic403' + '404': + $ref: '#/components/responses/Generic404' options: - tags: - - CAMARA Extended CloudEvents Common Subscription + tags: [CAMARA Extended CloudEvents Subscription] operationId: getCamaraCloudEventsSubscriptionFeatures - summary: getSubscriptionFeatures + summary: Discover CAMARA CloudEvents subscription features description: Discover supported features and methods for this endpoint security: - - openId: - - camara-cloudevents-subscriptions:read + - openId: [camara-cloudevents-subscriptions:read] parameters: - - $ref: "#/components/parameters/SubscriptionId" - - $ref: "#/components/parameters/x-correlator" + - $ref: '#/components/parameters/SubscriptionId' + - $ref: '#/components/parameters/x-correlator' responses: - "200": + '200': description: OK headers: Allow: schema: type: string - default: "GET,PUT,DELETE,OPTIONS" + default: GET,PUT,PATCH,DELETE,OPTIONS x-correlator: - $ref: "#/components/headers/x-correlator" - "400": - $ref: "#/components/responses/Generic400" - + $ref: '#/components/headers/x-correlator' + '400': + $ref: '#/components/responses/Generic400' components: securitySchemes: openId: - $ref: 'CAMARA_common.yaml#/components/securitySchemes/openId' + $ref: CAMARA_common.yaml#/components/securitySchemes/openId notificationsBearerAuth: - $ref: 'CAMARA_common.yaml#/components/securitySchemes/notificationsBearerAuth' - + $ref: CAMARA_common.yaml#/components/securitySchemes/notificationsBearerAuth parameters: SubscriptionId: name: id in: path - description: Subscription identifier that was obtained from the create event subscription operation. + description: Subscription identifier that was obtained from the create event + subscription operation. required: true schema: - $ref: "#/components/schemas/SubscriptionId" + $ref: '#/components/schemas/SubscriptionId' x-correlator: - $ref: 'CAMARA_common.yaml#/components/parameters/x-correlator' + $ref: CAMARA_common.yaml#/components/parameters/x-correlator If-None-Match: - $ref: 'CAMARA_common.yaml#/components/parameters/If-None-Match' + $ref: CAMARA_common.yaml#/components/parameters/If-None-Match If-Modified-Since: - $ref: 'CAMARA_common.yaml#/components/parameters/If-Modified-Since' - + $ref: CAMARA_common.yaml#/components/parameters/If-Modified-Since + If-Match: + $ref: CAMARA_common.yaml#/components/parameters/If-Match headers: x-correlator: - $ref: 'CAMARA_common.yaml#/components/headers/x-correlator' + $ref: CAMARA_common.yaml#/components/headers/x-correlator Cache-Control: - $ref: 'CAMARA_common.yaml#/components/headers/Cache-Control' + $ref: CAMARA_common.yaml#/components/headers/Cache-Control ETag: - $ref: 'CAMARA_common.yaml#/components/headers/ETag' + $ref: CAMARA_common.yaml#/components/headers/ETag Last-Modified: - $ref: 'CAMARA_common.yaml#/components/headers/Last-Modified' - + $ref: CAMARA_common.yaml#/components/headers/Last-Modified + Accept-Patch: + $ref: CAMARA_common.yaml#/components/headers/Accept-Patch schemas: ErrorInfo: - $ref: 'CAMARA_common.yaml#/components/schemas/ErrorInfo' - + $ref: CAMARA_common.yaml#/components/schemas/ErrorInfo + ResourceScopes: + $ref: CAMARA_common.yaml#/components/schemas/ResourceScopes SubscriptionId: type: string description: | @@ -374,73 +610,168 @@ components: within an event notification, this concept SHALL be referred as `subscriptionId` as per [Commonalities Event Notification Model](https://github.com/camaraproject/Commonalities/blob/main/documentation/API-design-guidelines.md#122-event-notification). example: qs15-h556-rt89-1298 - SubscriptionAsync: - description: Response for an event-type subscription request managed asynchronously (Creation or Deletion). + description: Response for an event-type subscription request managed asynchronously + (Creation or Deletion). type: object properties: id: - $ref: "#/components/schemas/SubscriptionId" - - CamaraExtendedSubscriptionRequest: + $ref: '#/components/schemas/SubscriptionId' + required: [id] + CamaraSubCreateOnly: type: object - additionalProperties: false description: | - Extended subscription request with enhanced config options. + Extended subscription request with enhanced config creation only options. + properties: + config: + $ref: '#/components/schemas/CamaraSubscriptionConfigCreateOnly' + CamaraSubUpdatable: + type: object + description: | + Extended subscription enhanced config updatable options at POST and change later. allOf: - - $ref: 'subscriptions-openapi.yaml#/components/schemas/SubscriptionRequest' + - $ref: subscriptions-openapi.yaml#/components/schemas/SubscriptionRequest - type: object properties: config: - $ref: "#/components/schemas/CamaraSubscriptionConfig" - required: - - types - - config - + $ref: '#/components/schemas/CamaraSubscriptionConfigUpdatable' + required: [types, config] + CamaraSubUpdateOnly: + type: object + description: | + Extended subscription enhanced config update only options. It toggles only meaningful post-creation option. + properties: + config: + $ref: '#/components/schemas/CamaraSubscriptionConfigUpdateOnly' + CamaraSubOutputOnly: + type: object + description: | + Extended subscription output only attribute. + properties: + id: + $ref: '#/components/schemas/SubscriptionId' + config: + $ref: '#/components/schemas/CamaraSubscriptionConfigOutputOnly' + CamaraExtendedSubscriptionRequest: + type: object + description: | + Extended subscription create request with enhanced config options. + allOf: + - $ref: '#/components/schemas/CamaraSubCreateOnly' + - $ref: '#/components/schemas/CamaraSubUpdatable' CamaraExtendedSubscription: type: object additionalProperties: false - title: "Subscription" + title: CamaraExtendedSubscription + description: | + Camara extended subscription. allOf: - - $ref: "#/components/schemas/CamaraExtendedSubscriptionRequest" - - type: object - properties: - id: - $ref: "#/components/schemas/SubscriptionId" - required: - - id - - sink - - protocol - - CamaraSubscriptionConfig: + - $ref: '#/components/schemas/CamaraSubCreateOnly' + - $ref: '#/components/schemas/CamaraSubUpdatable' + - $ref: '#/components/schemas/CamaraSubOutputOnly' + CamaraExtendedSubscriptionMergePatch: + type: object + additionalProperties: true + description: JSON Merge Patch (RFC 7396) over the set of fields that are mutable + post-creation. Only UpdateOnly and Updatable. Everything optional + nullable, + per RFC 7396. + allOf: + - $ref: '#/components/schemas/CamaraSubUpdateOnly' + - $ref: '#/components/schemas/CamaraSubUpdatable' + CamaraSubscriptionConfigCreateOnly: + description: | + Implementation-specific configuration parameters are needed by the subscription manager for acquiring events at POST. + In CAMARA we have predefined attributes like `initialEvent`. + Note: If a request is performed for several event types, all subscribed events will use the same `config` parameters. + type: object + additionalProperties: false + properties: + initialEvent: + type: boolean + description: | + Set to `true` by API consumer if consumer wants to get an event as soon as the subscription is created and current situation reflects event request. It applies to all event types. + Change request for this attribute using PUT or PATCH on existing subscription results in GENERIC_400_DISALLOWED_CHANGE error. + Example: Consumer request area entered event. If consumer sets initialEvent to true and device is already in the geofence, an event is triggered. + CamaraSubscriptionConfigUpdateOnly: description: | - Implementation-specific configuration parameters are needed by the subscription manager for acquiring events. - In CAMARA we have predefined attributes like `subscriptionExpireTime`, `subscriptionMaxEvents`, `initialEvent`. - Specific event type attributes must be defined in `subscriptionDetail`. + Implementation-specific configuration parameters are needed by the subscription manager for acquiring events at PUT or PATCH after POST. Note: If a request is performed for several event types, all subscribed events will use the same `config` parameters. type: object additionalProperties: false - required: - - subscriptionDetail properties: - subscriptionDetail: - $ref: "#/components/schemas/SubscriptionDetail" + status: + type: string + description: |- + Current overall status of the subscription - Management of Subscription State engine is not mandatory for now. It is not per event type being subscribed to. Note not all statuses may be considered to be implemented. Details: + - `ACTIVE`: Subscription creation process is completed. Subscription is fully operative. + - `INACTIVE`: Subscription is temporarily inactive, but its workflow logic is not deleted. + enum: [ACTIVE, INACTIVE] + CamaraSubscriptionConfigUpdatable: + description: | + Implementation-specific configuration parameters are needed by the subscription manager for acquiring events at POST, PUT or PATCH. + In CAMARA we have predefined attributes like `subscriptionExpireTime`, `subscriptionMaxEvents`. + Specific event type attributes must be defined in `subscriptionDetails`. + Note: If a request is performed for several event types, all subscribed events will use the same `config` parameters. + type: object + additionalProperties: false + required: [subscriptionDetails] + properties: + subscriptionDetails: + type: array + description: Base schema for all domain-specific subscriptionDetail definitions. + nullable: true + minItems: 1 + maxItems: 100 + items: + type: object + additionalProperties: false + required: [types, version, details] + properties: + types: + type: array + minItems: 1 + maxItems: 100 + items: + type: string + description: subscription detail types eligible to be delivered + by this subscription. + example: + - org.camaraproject.quality-on-demand.v1.detail + - org.camaraproject.geofencing-subscriptions.v1.detail + version: + type: string + description: Version number for this subscription detail. + details: + type: array + minItems: 1 + maxItems: 100 + description: Domain-specific attributes for the indicated subscription + detail types. + items: + $ref: '#/components/schemas/SubscriptionDetail' subscriptionStartTime: type: string format: date-time - example: "2023-01-17T13:18:23.682Z" - description: The subscription start time (in date-time format) requested by the API consumer. + example: '2023-01-17T13:18:23.682Z' + description: The subscription start time (in date-time format) requested + by the API consumer. + nullable: true subscriptionExpireTime: type: string format: date-time - example: "2023-01-17T13:18:23.682Z" - description: The subscription expiration time (in date-time format) requested by the API consumer. + example: '2023-01-17T13:18:23.682Z' + description: The subscription expiration time (in date-time format) requested + by the API consumer. Set this attribute to a time value in the past results + in GENERIC_400_DENIED_CHANGE error. + nullable: true subscriptionMaxEvents: type: integer description: | - Identifies the maximum number of event reports to be generated (>=1) requested by the API consumer - Once this number is reached, the subscription ends. + Identifies the maximum total number of event reports to be generated (>=1) requested by the API consumer - Once this number is reached, the subscription ends. Note on combined usage of `initialEvent` and `subscriptionMaxEvents`: If an event is triggered following `initialEvent` set to `true`, this event will be counted towards `subscriptionMaxEvents`. + It is not per event type and it is not batch count. + nullable: true minimum: 1 example: 5 eventBatchSize: @@ -448,6 +779,7 @@ components: description: | Identifies the maximum number of event reports to be generated (>=1) ina a batch requested by the API consumer - Once this number is reached for current batch, the events emit to the 'sink'. Batching: Events are pushed in batches of up to config.eventBatchSize. + nullable: true minimum: 1 example: 5 cacheResyncRequest: @@ -455,52 +787,147 @@ components: description: | Set to `true` by API consumer if consumer wants to get cached state as soon as the subscription is created. A cache resync isn't a request for historical event data. It only restores the current cache state. - Treat a cache resync request as if 'initialEvent' = 'true' and 'subscriptionStartTime' is now. 'eventResyncTime' value, if provided, is ignored by cache resync operation. + nullable: true eventResyncTime: type: string format: date-time - example: "2023-01-17T13:18:23.682Z" - description: The event resync start time (in date-time format) requested by the API consumer. + example: '2023-01-17T13:18:23.682Z' + description: The event resync start time (in date-time format) requested + by the API consumer. + nullable: true eventResyncRequest: type: boolean description: | Set to `true` by API consumer if consumer wants to get historical events as soon as the subscription is created. Treat the event resync request as if 'initialEvent' = 'true' and use the provided 'eventResyncTime' in place of 'subscriptionStartTime'. - Event resync becomes truly historical only if the system retains every event and can replay them all. In practice, we should treat event resync as a “best effort” operation, dependent on what the implementation can actually provide. Not every API needs or should offer a batching/resync capability. - initialEvent: - type: boolean + nullable: true + notificationPolicy: + $ref: '#/components/schemas/NotificationPolicy' + NotificationPolicy: + description: | + CloudEvents notification delivery policy. + type: object + properties: + periodicityResourceScopes: + $ref: '#/components/schemas/ResourceScopes' + periodicity: + type: string description: | - Set to `true` by API consumer if consumer wants to get an event as soon as the subscription is created and current situation reflects event request. - Example: Consumer request area entered event. If consumer sets initialEvent to true and device is already in the geofence, an event is triggered. + ISO-8601 duration indicating the **scheduled emission cadence** for this subscription. + When present, the server creates a scheduler that emits events on each tick until + `subscriptionExpireTime` or explicit deletion. + Semantics: + - Omitted ⇒ no scheduler (pure event-driven behavior). + - Example values: + `PT1H` → every 1 hour + `PT15M` → every 15 minutes + `P1D` → once per day + - The first tick is determined by `subscriptionStartTime` and optional `alignment`. + - The CloudEvent `time` reflects the scheduled tick instant. + example: PT1H + nullable: true + alignment: + type: string + format: date-time + description: | + Optional **anchor timestamp** to align ticks to a wall-clock boundary. + If provided with `periodicity: PT1H`, ticks align to the top of the hour relative + to this anchor (e.g., 12:00, 13:00, 14:00…). If omitted, the first tick occurs + at or after `subscriptionStartTime` and subsequent ticks follow `periodicity`. + Notes: + - If `subscriptionStartTime` < now and `alignment` is set, the next tick is the + first aligned instant ≥ now. + - Must be RFC 3339/ISO 8601 timestamp. + example: '2025-10-29T12:00:00Z' + nullable: true + eventMode: + type: string + enum: [snapshot, changes, digest] + default: snapshot + description: | + Controls **what** is emitted on each scheduled tick when `periodicity` is present. + - `snapshot` → emit the current state for the selected `resourceScopes` every tick, + even if no changes occurred. + - `changes` → emit only if any relevant state changed since the previous tick + (implementations MAY send a minimal heartbeat with `data.noChange: true`). + - `digest` → emit an **aggregate** for the interval (see `window`). + If `periodicity` is omitted, `eventMode` has no effect. + nullable: true + window: + type: string + description: | + ISO-8601 duration that defines the **aggregation interval** used when + `eventMode: digest` is selected. Defaults to `periodicity` if not provided. + Examples: + - With `periodicity: PT1H` and `window: PT1H`, emit hourly roll-ups. + - With `periodicity: PT1H` and `window: P1D`, emit a daily roll-up once per hour + (implementations MAY coalesce and emit only on the window boundary). + Ignored for `snapshot` and `changes`. + example: PT1H + nullable: true + maxEventsPerTick: + type: integer + minimum: 1 + description: | + Maximum number of CloudEvents the server may emit per scheduled tick + for this subscription. Used to limit fan-out when the referenced + `resourceScopes` include many resources (for example, a large device group). + Semantics: + - When omitted, the server uses its own internal batching policy. + - When provided, the server SHOULD partition the dataset and deliver + up to `maxEventsPerTick` events per tick, adding `data.part` / + `data.partCount` metadata to each CloudEvent for reassembly. + - This property has effect only when `periodicity` is set. + Example: + `maxEventsPerTick: 100` → emit up to 100 events each hour per tick. + example: 100 + nullable: true + deliveryMode: + type: string + description: | + Defines **when** the subscription server delivers notifications + relative to event occurrence and policy evaluation. + - `IMMEDIATE`: deliver each qualifying event as soon as it is produced + (default CAMARA behavior, equivalent to real-time push). + - `PERIODIC`: deliver accumulated or aggregated results on a fixed cadence + defined by `periodicity` and optionally aligned using `alignment`. + enum: [IMMEDIATE, PERIODIC] + default: IMMEDIATE + nullable: true + CamaraSubscriptionConfigOutputOnly: + description: | + Implementation-specific configuration parameters output from the subscription manager for acquiring events. + type: object + additionalProperties: false + properties: startsAt: type: string - readOnly: true format: date-time - description: Date when the event subscription will begin/began. This attribute must not be present in the POST request as it is provided by API server. It must be present in GET endpoints. + description: Date when the event subscription will begin/began. This attribute + must not be present in the POST request as it is provided by API server. + It must be present in GET endpoints. expiresAt: type: string - readOnly: true format: date-time description: | Date when the event subscription will expire. Only provided when `subscriptionExpireTime` is indicated by API client or Telco Operator has a specific policy about that. This attribute must not be present in the POST request as it is provided (optionally) by API server. This attribute must be provided by the server if subscriptionExpireTime is provided in the request and server is not able to handle it. + nullable: true status: type: string - readOnly: true description: |- - Current status of the subscription - Management of Subscription State engine is not mandatory for now. Note not all statuses may be considered to be implemented. Details: - - `ACTIVATION_REQUESTED`: Subscription creation (POST) is triggered but subscription creation process is not finished yet. + Current overall status of the subscription - Management of Subscription State engine is not mandatory for now. It is not per event type being subscribed to. Note not all statuses may be considered to be implemented. Details: + - `ACTIVATION_REQUESTED`: Subscription creation (POST) is triggered but subscription creation process is not finished yet and validation handshake maybe is pending per CloudEvents HTTP WebHook. - `CACHE_RESYNCING`: current cache state restore in progress. - `CACHE_RESYNC_COMPLETED`: current cache state restored. - `EVENT_RESYNCING`: historical events replay in progress. - `EVENT_RESYNC_COMPLETED`: historical events replay completed. - `ACTIVE`: Subscription creation process is completed. Subscription is fully operative. - - `INACTIVE`: Subscription is temporarily inactive, but its workflow logic is not deleted. - `EXPIRED`: Subscription is ended (no longer active). This status applies when subscription is ended due to `SUBSCRIPTION_EXPIRED` or `ACCESS_TOKEN_EXPIRED` event. - `DELETED`: Subscription is ended as deleted (no longer active). This status applies when subscription information is kept (i.e. subscription workflow is no longer active but its meta-information is kept). enum: @@ -511,13 +938,114 @@ components: - EVENT_RESYNC_COMPLETED - ACTIVE - EXPIRED - - INACTIVE - DELETED - + nullable: true + CamaraExtendedJsonPatchOperation: + description: One RFC 6902 JSON Patch operation + type: object + additionalProperties: false + properties: + op: + type: string + description: operation + enum: [add, remove, replace, move, copy, test] + path: + type: string + description: JSON Pointer (RFC 6901) + from: + type: string + description: JSON Pointer; required for move/copy + value: + description: | + The value to be used within the operation. + Its type depends on the target path: it may be a string, number, + boolean, object, array, or null. + oneOf: + - type: string + nullable: true + - type: number + nullable: true + - type: boolean + nullable: true + - type: object + nullable: true + - type: array + items: {} + nullable: true + # Enforce valid combos of required fields: + oneOf: + - required: [op, path, value] # add/replace/test + properties: + op: {enum: [add, replace, test]} + - required: [op, path, from] # move/copy + properties: + op: {enum: [move, copy]} + - required: [op, path] # remove + properties: + op: {enum: [remove]} + CamaraConfigChangeEventBase: + description: | + CamaraConfigChangeEventBase + allOf: + - $ref: '#/components/schemas/SubscriptionId' + - type: object + properties: + camaraConfigBaseVersion: + type: string + description: Version/ETag this change applies to. + camaraConfigResultVersion: + type: string + description: Version/ETag after applying this change. + camaraSeq: + type: string + description: Monotonic sequence per subscription (provider-defined). + CamaraConfigChangeEventJsonPatch: + description: | + CamaraConfigChangeEventJsonPatch + allOf: + - $ref: '#/components/schemas/CamaraConfigChangeEventBase' + - type: object + properties: + datacontenttype: + type: string + enum: [application/json-patch+json] + data: + type: array + description: JSON Patch operations applied to the *Subscription* representation + (root at '/'). + items: + $ref: '#/components/schemas/CamaraExtendedJsonPatchOperation' + CamaraConfigChangeEventMergePatch: + description: | + CamaraConfigChangeEventMergePatch + allOf: + - $ref: '#/components/schemas/CamaraConfigChangeEventBase' + - type: object + properties: + datacontenttype: + type: string + enum: [application/merge-patch+json] + data: + $ref: '#/components/schemas/CamaraExtendedSubscription' + CamaraConfigChangeEventSnapshot: + description: | + CamaraConfigChangeEventSnapshot + allOf: + - $ref: '#/components/schemas/CamaraConfigChangeEventBase' + - type: object + properties: + datacontenttype: + type: string + enum: [application/json] + data: + type: object + required: [previous, current] + properties: + previous: {$ref: '#/components/schemas/CamaraExtendedSubscription'} + current: {$ref: '#/components/schemas/CamaraExtendedSubscription'} SubscriptionDetail: type: object description: Base schema for all domain-specific subscriptionDetail definitions. - CamaraExtendedCloudEventsAttribute: type: object description: | @@ -529,28 +1057,25 @@ components: - specversion - type - time - 'datacontenttype': 'media-type that describes the event payload encoding, must be "application/json" for CAMARA APIs' 'type' example: org.camaraproject.device-reachability-status-subscriptions.v0.reachability-data allOf: - - $ref: 'subscriptions-openapi.yaml#/components/schemas/CloudEventsAttribute' + - $ref: subscriptions-openapi.yaml#/components/schemas/CloudEventsAttribute - type: object properties: data: - $ref: "#/components/schemas/CamaraCloudEventData" - required: - - id - - source - - specversion - - type - - time - - data + $ref: '#/components/schemas/CamaraCloudEventData' + camaraConfigVersion: + type: string + description: Opaque version or hash of the effective subscription config + required: [id, source, specversion, type, time, data] discriminator: - propertyName: "type" - + propertyName: type CamaraCloudEventData: type: object - description: Event details payload described in each CAMARA API and referenced by its type + description: Event details payload described in each CAMARA API and referenced + by its type + nullable: true additionalProperties: true # allow any type properties: syncStatus: @@ -562,58 +1087,107 @@ components: - EVENT_RESYNC_COMPLETED description: | Optional. If present, indicates the subscription's sync phase: - • `CACHE_RESYNCING`: current cache state restore in progress. - • `CACHE_RESYNC_COMPLETED`: current cache state restored. - • `EVENT_RESYNCING`: historical events replay in progress. - • `EVENT_RESYNC_COMPLETED`: historical events replay completed. - + - `CACHE_RESYNCING`: current cache state restore in progress. + - `CACHE_RESYNC_COMPLETED`: current cache state restored. + - `EVENT_RESYNCING`: historical events replay in progress. + - `EVENT_RESYNC_COMPLETED`: historical events replay completed. + camaraMeta: + type: object + description: | + CAMARA-reserved metadata that augments domain payloads with scheduling, + batching, and reassembly hints. Vendors SHOULD place platform-level + metadata here to avoid collisions with domain fields. + additionalProperties: false + properties: + periodic: + type: object + description: Metadata for periodic/partitioned emissions. + additionalProperties: false + properties: + noChange: + type: boolean + description: | + True if no relevant state changed during this tick. Indicates a heartbeat event. + example: true + part: + type: integer + minimum: 1 + description: 1-based index of this part among multiple parts for + the same tick. + example: 1 + partCount: + type: integer + minimum: 1 + description: Total number of parts emitted for this tick. + example: 3 + tickTime: + type: string + format: date-time + description: | + Scheduled tick timestamp (should match CloudEvent `time`), useful for reassembly and dedupe. + example: '2025-10-29T13:00:00Z' + InitiationReason: + type: string + description: | + - SUBSCRIPTION_CREATED - Subscription created by API Server + enum: [SUBSCRIPTION_CREATED] + UpdateReason: + type: string + description: | + - SUBSCRIPTION_ACTIVE - API server transitioned susbcription status to `ACTIVE` + - SUBSCRIPTION_INACTIVE - API server transitioned susbcription status to `INACTIVE` + enum: [SUBSCRIPTION_ACTIVE, SUBSCRIPTION_INACTIVE] TerminationReason: type: string description: | - NETWORK_TERMINATED - API server stopped sending notification + - SUBSCRIPTION_UNPROCESSABLE - Subscription cannot be processed due to some reason, e.g. because the specified area cannot be managed. Useful for asynchronous subscription creation. - SUBSCRIPTION_EXPIRED - Subscription expire time (optionally set by the requester) has been reached + - SUBSCRIPTION_DELETED - Subscription was deleted by the requester - MAX_EVENTS_REACHED - Maximum number of events (optionally set by the requester) has been reached - ACCESS_TOKEN_EXPIRED - Access Token sinkCredential (optionally set by the requester) expiration time has been reached - - SUBSCRIPTION_DELETED - Subscription was deleted by the requester enum: - MAX_EVENTS_REACHED - NETWORK_TERMINATED + - SUBSCRIPTION_UNPROCESSABLE - SUBSCRIPTION_EXPIRED - - ACCESS_TOKEN_EXPIRED - SUBSCRIPTION_DELETED - + - ACCESS_TOKEN_EXPIRED responses: + Generic304: + $ref: CAMARA_common.yaml#/components/responses/Generic304 Generic400: - $ref: "CAMARA_common.yaml#/components/responses/Generic400" - + $ref: CAMARA_common.yaml#/components/responses/Generic400 CreateSubscriptionBadRequest400: description: Problem with the client request. headers: x-correlator: - $ref: "#/components/headers/x-correlator" + $ref: '#/components/headers/x-correlator' content: application/json: schema: title: CreateSubscriptionBadRequest400 allOf: - - $ref: "#/components/schemas/ErrorInfo" + - $ref: '#/components/schemas/ErrorInfo' - type: object properties: status: - enum: - - 400 + enum: [400] code: enum: - INVALID_ARGUMENT - INVALID_CREDENTIAL - INVALID_PROTOCOL - INVALID_TOKEN + - DENIED_CHANGE + - DISALLOWED_CHANGE examples: GENERIC_400_INVALID_ARGUMENT: value: status: 400 code: INVALID_ARGUMENT - message: Client specified an invalid argument, request body or query param. + message: Client specified an invalid argument, request body or query + param. GENERIC_400_INVALID_PROTOCOL: value: status: 400 @@ -629,116 +1203,122 @@ components: status: 400 code: INVALID_TOKEN message: Only bearer token is supported. - + GENERIC_400_DENIED_CHANGE: + value: + status: 400 + code: DENIED_CHANGE + message: Change request is allowed but denied at this moment. + GENERIC_400_DISALLOWED_CHANGE: + value: + status: 400 + code: DISALLOWED_CHANGE + message: Change request is always not allowed. SubscriptionIdRequired400: description: Problem with the client request headers: x-correlator: - $ref: "#/components/headers/x-correlator" + $ref: '#/components/headers/x-correlator' content: application/json: schema: title: SubscriptionIdRequired400 allOf: - - $ref: "#/components/schemas/ErrorInfo" + - $ref: '#/components/schemas/ErrorInfo' - type: object properties: status: - enum: - - 400 + enum: [400] code: - enum: - - INVALID_ARGUMENT + enum: [INVALID_ARGUMENT] examples: GENERIC_400_INVALID_ARGUMENT: summary: Schema validation failed value: status: 400 code: INVALID_ARGUMENT - message: Client specified an invalid argument, request body or query param. + message: Client specified an invalid argument, request body or query + param. GENERIC_400_SUBSCRIPTION_ID_REQUIRED: summary: The subscription id is required value: status: 400 code: INVALID_ARGUMENT - message: "Expected property is missing: subscriptionId" - + message: 'Expected property is missing: subscriptionId' Generic401: - $ref: "CAMARA_common.yaml#/components/responses/Generic401" - + $ref: CAMARA_common.yaml#/components/responses/Generic401 Generic403: - $ref: "CAMARA_common.yaml#/components/responses/Generic403" - + $ref: CAMARA_common.yaml#/components/responses/Generic403 SubscriptionPermissionDenied403: description: Client does not have sufficient permission. headers: x-correlator: - $ref: "#/components/headers/x-correlator" + $ref: '#/components/headers/x-correlator' content: application/json: schema: title: SubscriptionPermissionDenied403 allOf: - - $ref: "#/components/schemas/ErrorInfo" + - $ref: '#/components/schemas/ErrorInfo' - type: object properties: status: - enum: - - 403 + enum: [403] code: - enum: - - PERMISSION_DENIED - - SUBSCRIPTION_MISMATCH + enum: [PERMISSION_DENIED, SUBSCRIPTION_MISMATCH] examples: GENERIC_403_PERMISSION_DENIED: value: status: 403 code: PERMISSION_DENIED - message: Client does not have sufficient permissions to perform this action. + message: Client does not have sufficient permissions to perform this + action. GENERIC_403_TOKEN_MISMATCH: value: status: 403 code: SUBSCRIPTION_MISMATCH message: Inconsistent access token for requested events subscription. - Generic404: - $ref: "CAMARA_common.yaml#/components/responses/Generic404" - + $ref: CAMARA_common.yaml#/components/responses/Generic404 Generic409: - $ref: "CAMARA_common.yaml#/components/responses/Generic409" - + $ref: CAMARA_common.yaml#/components/responses/Generic409 Generic410: - $ref: "CAMARA_common.yaml#/components/responses/Generic410" - + $ref: CAMARA_common.yaml#/components/responses/Generic410 + Generic412: + $ref: CAMARA_common.yaml#/components/responses/Generic412 + Generic415: + $ref: CAMARA_common.yaml#/components/responses/Generic415 CreateSubscriptionUnprocessableEntity422: description: Unprocessable Entity headers: x-correlator: - $ref: "#/components/headers/x-correlator" + $ref: '#/components/headers/x-correlator' content: application/json: schema: title: CreateSubscriptionUnprocessableEntity422 allOf: - - $ref: "#/components/schemas/ErrorInfo" + - $ref: '#/components/schemas/ErrorInfo' - type: object properties: status: - enum: - - 422 + enum: [422] code: enum: - IDENTIFIER_MISMATCH - MISSING_IDENTIFIER - - MULTIEVENT_SUBSCRIPTION_NOT_SUPPORTED - SERVICE_NOT_APPLICABLE - UNNECESSARY_IDENTIFIER - UNSUPPORTED_IDENTIFIER - GEOFENCING_SUBSCRIPTIONS.AREA_NOT_COVERED - GEOFENCING_SUBSCRIPTIONS.INVALID_AREA + - GROUP_SUBSCRIPTIONS.INVALID_GROUP + - NOTIFICATION_POLICY_NOT_SUPPORTED + - INVALID_NOTIFICATION_POLICY + - SEMANTIC_RULE_VIOLATED examples: GENERIC_422_IDENTIFIER_MISMATCH: - description: Inconsistency between device identifiers not pointing to the same device. + description: Inconsistency between device identifiers not pointing to + the same device. value: status: 422 code: IDENTIFIER_MISMATCH @@ -750,18 +1330,16 @@ components: code: SERVICE_NOT_APPLICABLE message: The service is not available for the provided identifier. GENERIC_422_MISSING_IDENTIFIER: - description: An identifier is not included in the request and the device or phone number identification cannot be derived from the 3-legged access token + description: An identifier is not included in the request and the device + or phone number identification cannot be derived from the 3-legged + access token value: status: 422 code: MISSING_IDENTIFIER message: The device cannot be identified. - GENERIC_422_MULTIEVENT_SUBSCRIPTION_NOT_SUPPORTED: - value: - status: 422 - code: MULTIEVENT_SUBSCRIPTION_NOT_SUPPORTED - message: Multi event types subscription not managed. GENERIC_422_UNNECESSARY_IDENTIFIER: - description: An explicit identifier is provided when a device or phone number has already been identified from the access token + description: An explicit identifier is provided when a device or phone + number has already been identified from the access token value: status: 422 code: UNNECESSARY_IDENTIFIER @@ -778,14 +1356,42 @@ components: value: status: 422 code: GEOFENCING_SUBSCRIPTIONS.AREA_NOT_COVERED - message: "Unable to cover the requested area" + message: Unable to cover the requested area GEOFENCING_422_INVALID_AREA: summary: Invalid area - description: The requested area is too small to be supported by the system. + description: The requested area is too small to be supported by the + system. value: status: 422 code: GEOFENCING_SUBSCRIPTIONS.INVALID_AREA - message: "The requested area is too small" - + message: The requested area is too small + GROUP_422_INVALID_GROUP: + summary: Invalid group identifier + description: The requested group identifier is not valid. + value: + status: 422 + code: GROUP_SUBSCRIPTIONS.INVALID_GROUP + message: The requested group identifier is not valid. + NOTIFICATION_POLICY_NOT_SUPPORTED: + summary: Notification policy is not supported + description: Notification policy is not supported + value: + status: 422 + code: NOTIFICATION_POLICY_NOT_SUPPORTED + message: Notificatio policy is not supportedd. + INVALID_NOTIFICATION_POLICY: + summary: Notification policy configuration is invalid + description: Notification policy configuration is invalid + value: + status: 422 + code: INVALID_NOTIFICATION_POLICY + message: Notification policy configuration is invalid. + SEMANTIC_RULE_VIOLATED: + summary: Semantic rule violated + description: Semantic rule violated (e.g., forbidden state transition) + value: + status: 422 + code: SEMANTIC_RULE_VIOLATED + message: Semantic rule violated. Generic429: - $ref: "CAMARA_common.yaml#/components/responses/Generic429" + $ref: CAMARA_common.yaml#/components/responses/Generic429 diff --git a/code/API_definitions/CAMARA_common.yaml b/code/API_definitions/CAMARA_common.yaml index 934721d..c2ddd8d 100644 --- a/code/API_definitions/CAMARA_common.yaml +++ b/code/API_definitions/CAMARA_common.yaml @@ -1,3 +1,4 @@ +--- openapi: 3.0.3 info: title: CAMARA common data types @@ -6,8 +7,7 @@ info: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0.html version: wip - x-camara-commonalities: 0.6 - + x-camara-commonalities: tbd paths: {} components: securitySchemes: @@ -19,12 +19,12 @@ components: description: Notification bearer authentication. type: http scheme: bearer - bearerFormat: "{$request.body#/sinkCredential.credentialType}" + bearerFormat: '{$request.body#/sinkCredential.credentialType}' headers: x-correlator: description: Correlation id for the different services schema: - $ref: "#/components/schemas/XCorrelator" + $ref: '#/components/schemas/XCorrelator' Cache-Control: description: Public cacheable for 10 minutes schema: @@ -39,13 +39,25 @@ components: schema: type: string format: date-time + Accept-Patch: + description: Advertises which media types the server is able to understand in + a PATCH request + schema: + type: string + example: application/merge-patch+json, application/json-patch+json parameters: x-correlator: name: x-correlator in: header description: Correlation id for the different services schema: - $ref: "#/components/schemas/XCorrelator" + $ref: '#/components/schemas/XCorrelator' + If-Match: + name: If-Match + in: header + description: Apply only if the ETag matches (RFC 7232). + schema: + type: string If-None-Match: name: If-None-Match in: header @@ -59,70 +71,75 @@ components: schema: type: string format: date-time + GroupId: + name: GroupId + in: path + required: true + description: Reference Id for a created group + schema: + type: string + format: uuid schemas: XCorrelator: type: string + description: XCorrelator pattern: ^[a-zA-Z0-9-_:;.\/<>{}]{0,256}$ - example: "b4333c46-49c0-4f62-80d7-f0ef930f1c46" - + example: b4333c46-49c0-4f62-80d7-f0ef930f1c46 TimePeriod: + type: object + description: TimePeriod properties: startDate: type: string format: date-time - description: An instant of time, starting of the TimePeriod. It must follow [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) and must have time zone. + description: An instant of time, starting of the TimePeriod. It must follow + [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) + and must have time zone. endDate: type: string format: date-time - description: An instant of time, ending of the TimePeriod. If not included, then the period has no ending date. It must follow [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) and must have time zone. - required: - - startDate - + description: An instant of time, ending of the TimePeriod. If not included, + then the period has no ending date. It must follow [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) + and must have time zone. + required: [startDate] ErrorInfo: type: object - required: - - message - - status - - code + description: ErrorInfo + required: [status, code, message] properties: - message: - type: string - description: A human-readable description of what the event represents status: type: integer description: HTTP response status code code: type: string description: A human-readable code to describe the error - + message: + type: string + description: A human-readable description of what the event represents ApplicationServer: description: | A server hosting backend applications to deliver some business logic to clients. - The developer can choose to provide the below specified device identifiers: - * `ipv4Address` * `ipv6Address` type: object properties: ipv4Address: - $ref: "#/components/schemas/ApplicationServerIpv4Address" + $ref: '#/components/schemas/ApplicationServerIpv4Address' ipv6Address: - $ref: "#/components/schemas/ApplicationServerIpv6Address" + $ref: '#/components/schemas/ApplicationServerIpv6Address' minProperties: 1 - ApplicationServerIpv4Address: type: string - example: "198.51.100.0/24" + example: 198.51.100.0/24 description: | IPv4 address may be specified in form
as: - address - an IPv4 number in dotted-quad form 1.2.3.4. Only this exact IP number will match the flow control rule. - address/mask - an IP number as above with a mask width of the form 1.2.3.4/24. In this case, all IP numbers from 1.2.3.0 to 1.2.3.255 will match. The bit width MUST be valid for the IP version. - ApplicationServerIpv6Address: type: string - example: "2001:db8:85a3:8d3:1319:8a2e:370:7344" + example: 2001:db8:85a3:8d3:1319:8a2e:370:7344 description: | IPv6 address may be specified in form
as: - address - The /128 subnet is optional for single addresses: @@ -131,7 +148,6 @@ components: - address/mask - an IP v6 number with a mask: - 2001:db8:85a3:8d3::0/64 - 2001:db8:85a3:8d3::/64 - Device: description: | End-user equipment able to connect to a mobile network. Examples of devices include smartphones or IoT sensors/actuators. @@ -145,72 +161,67 @@ components: type: object properties: phoneNumber: - $ref: "#/components/schemas/PhoneNumber" + $ref: '#/components/schemas/PhoneNumber' networkAccessIdentifier: - $ref: "#/components/schemas/NetworkAccessIdentifier" + $ref: '#/components/schemas/NetworkAccessIdentifier' ipv4Address: - $ref: "#/components/schemas/DeviceIpv4Addr" + $ref: '#/components/schemas/DeviceIpv4Addr' ipv6Address: - $ref: "#/components/schemas/DeviceIpv6Address" + $ref: '#/components/schemas/DeviceIpv6Address' minProperties: 1 - DeviceResponse: description: | An identifier for the end-user equipment able to connect to the network that the response refers to. This parameter is only returned when the API consumer includes the `device` parameter in their request (i.e. they are using a two-legged access token), and is relevant when more than one device identifier is specified, as only one of those device identifiers is allowed in the response. - If the API consumer provides more than one device identifier in their request, and this schema is included in the response definition, the API provider MUST use it to return a single identifier which is the one they are using to fulfil the request, even if the identifiers do not match the same device. API provider does not perform any logic to validate/correlate that the indicated device identifiers match the same device. No error should be returned if the identifiers are otherwise valid to prevent API consumers correlating different identifiers with a given end user. - allOf: - - $ref: "#/components/schemas/Device" + - $ref: '#/components/schemas/Device' - maxProperties: 1 - PhoneNumber: - description: A public identifier addressing a telephone subscription. In mobile networks it corresponds to the MSISDN (Mobile Station International Subscriber Directory Number). In order to be globally unique it has to be formatted in international format, according to E.164 standard, prefixed with '+'. + description: A public identifier addressing a telephone subscription. In mobile + networks it corresponds to the MSISDN (Mobile Station International Subscriber + Directory Number). In order to be globally unique it has to be formatted in + international format, according to E.164 standard, prefixed with '+'. type: string - pattern: '^\+[1-9][0-9]{4,14}$' - example: "+123456789" - + pattern: ^\+[1-9][0-9]{4,14}$ + example: '+123456789' NetworkAccessIdentifier: - description: A public identifier addressing a subscription in a mobile network. In 3GPP terminology, it corresponds to the GPSI formatted with the External Identifier ({Local Identifier}@{Domain Identifier}). Unlike the telephone number, the network access identifier is not subjected to portability ruling in force, and is individually managed by each operator. + description: A public identifier addressing a subscription in a mobile network. + In 3GPP terminology, it corresponds to the GPSI formatted with the External + Identifier ({Local Identifier}@{Domain Identifier}). Unlike the telephone + number, the network access identifier is not subjected to portability ruling + in force, and is individually managed by each operator. type: string - example: "123456789@domain.com" - + example: 123456789@example.com DeviceIpv4Addr: type: object description: | The device should be identified by either the public (observed) IP address and port as seen by the application server, or the private (local) and any public (observed) IP addresses in use by the device (this information can be obtained by various means, for example from some DNS servers). - If the allocated and observed IP addresses are the same (i.e. NAT is not in use) then the same address should be specified for both publicAddress and privateAddress. - If NAT64 is in use, the device should be identified by its publicAddress and publicPort, or separately by its allocated IPv6 address (field ipv6Address of the Device object) - In all cases, publicAddress must be specified, along with at least one of either privateAddress or publicPort, dependent upon which is known. In general, mobile devices cannot be identified by their public IPv4 address alone. properties: publicAddress: - $ref: "#/components/schemas/SingleIpv4Addr" + $ref: '#/components/schemas/SingleIpv4Addr' privateAddress: - $ref: "#/components/schemas/SingleIpv4Addr" + $ref: '#/components/schemas/SingleIpv4Addr' publicPort: - $ref: "#/components/schemas/Port" + $ref: '#/components/schemas/Port' anyOf: - required: [publicAddress, privateAddress] - required: [publicAddress, publicPort] example: - publicAddress: "84.125.93.10" + publicAddress: 84.125.93.10 publicPort: 59765 - SingleIpv4Addr: description: A single IPv4 address with no subnet mask type: string format: ipv4 - example: "84.125.93.10" - + example: 84.125.93.10 Port: description: TCP or UDP port number type: integer minimum: 0 maximum: 65535 - PortsSpec: description: Specification of several TCP or UDP ports type: object @@ -222,109 +233,90 @@ components: minItems: 1 items: type: object - required: - - from - - to + required: [from, to] properties: from: - $ref: "#/components/schemas/Port" + $ref: '#/components/schemas/Port' to: - $ref: "#/components/schemas/Port" + $ref: '#/components/schemas/Port' ports: description: Array of TCP or UDP ports type: array minItems: 1 items: - $ref: "#/components/schemas/Port" + $ref: '#/components/schemas/Port' example: ranges: - from: 5010 to: 5020 - ports: - - 5060 - - 5070 - + ports: [5060, 5070] DeviceIpv6Address: description: | The device should be identified by the observed IPv6 address, or by any single IPv6 address from within the subnet allocated to the device (e.g. adding ::0 to the /64 prefix). type: string format: ipv6 example: 2001:db8:85a3:8d3:1319:8a2e:370:7344 - Area: description: Base schema for all areas type: object properties: areaType: - $ref: "#/components/schemas/AreaType" - required: - - areaType + $ref: '#/components/schemas/AreaType' + required: [areaType] discriminator: propertyName: areaType mapping: - CIRCLE: "#/components/schemas/Circle" - POLYGON: "#/components/schemas/Polygon" - + CIRCLE: '#/components/schemas/Circle' + POLYGON: '#/components/schemas/Polygon' AreaType: type: string description: | Type of this area. CIRCLE - The area is defined as a circle. POLYGON - The area is defined as a polygon. - enum: - - CIRCLE - - POLYGON - + enum: [CIRCLE, POLYGON] Circle: description: Circular area allOf: - - $ref: "#/components/schemas/Area" + - $ref: '#/components/schemas/Area' - type: object - required: - - center - - radius + required: [center, radius] properties: center: - $ref: "#/components/schemas/Point" + $ref: '#/components/schemas/Point' radius: type: number description: Distance from the center in meters minimum: 1 - Polygon: - description: Polygonal area. The Polygon should be a simple polygon, i.e. should not intersect itself. + description: Polygonal area. The Polygon should be a simple polygon, i.e. should + not intersect itself. allOf: - - $ref: "#/components/schemas/Area" + - $ref: '#/components/schemas/Area' - type: object - required: - - boundary + required: [boundary] properties: boundary: - $ref: "#/components/schemas/PointList" - + $ref: '#/components/schemas/PointList' PointList: description: List of points defining a polygon type: array items: - $ref: "#/components/schemas/Point" + $ref: '#/components/schemas/Point' minItems: 3 maxItems: 15 - Point: type: object description: Coordinates (latitude, longitude) defining a location in a map - required: - - latitude - - longitude + required: [latitude, longitude] properties: latitude: - $ref: "#/components/schemas/Latitude" + $ref: '#/components/schemas/Latitude' longitude: - $ref: "#/components/schemas/Longitude" + $ref: '#/components/schemas/Longitude' example: latitude: 50.735851 longitude: 7.10066 - QosProfileName: description: | A unique name for identifying a specific QoS profile. @@ -339,190 +331,228 @@ components: minLength: 3 maxLength: 256 format: string - pattern: "^[a-zA-Z0-9_.-]+$" - + pattern: ^[a-zA-Z0-9_.-]+$ Latitude: description: Latitude component of a location type: number format: double minimum: -90 maximum: 90 - Longitude: description: Longitude component of location type: number format: double minimum: -180 maximum: 180 - + GroupId: + description: Reference Id for a created group + type: string + format: uuid + ResourceScopes: + description: A list of resource scopes + type: array + items: + anyOf: + - $ref: '#/components/schemas/Device' + - $ref: '#/components/schemas/Area' + - $ref: '#/components/schemas/GroupId' + - $ref: '#/components/schemas/PortsSpec' responses: -####################################################### -####################################################### -# ERROR RESPONSE SCHEMA TEMPLATE -# - Objective: Make normative error `status` and `code` values -# - Schema Template rationale: -# - The `allOf` in content.application/json.schema allows a combination of both the generic ErrorInfo schema and the specific schema for this error response, -# which validates that `status` and `code` have only the specified values. -# This `allOf` is used without discriminator because it does not imply any hierarchy between the models, just 2 schemas that must be independently validated. -####################################################### -# ErrorResponseSchema: -# ... -# content: -# application/json: -# schema: -# allOf: -# - $ref: '#/components/schemas/ErrorInfo' -# - type: object -# properties: -# status: -# enum: -# - -# code: -# enum: -# - -# - -# examples: -# ExampleKey1: -# value: -# status: -# code: -# message: -# ExampleKey2: -# value: -# status: -# code: -# message: -####################################################### -####################################################### + ####################################################### + ####################################################### + # ERROR RESPONSE SCHEMA TEMPLATE + # - Objective: Make normative error `status` and `code` values + # - Schema Template rationale: + # - The `allOf` in content.application/json.schema allows a combination of both the generic ErrorInfo schema and the specific schema for this error response, + # which validates that `status` and `code` have only the specified values. + # This `allOf` is used without discriminator because it does not imply any hierarchy between the models, just 2 schemas that must be independently validated. + ####################################################### + # ErrorResponseSchema: + # ... + # content: + # application/json: + # schema: + # allOf: + # - $ref: '#/components/schemas/ErrorInfo' + # - type: object + # properties: + # status: + # enum: + # - + # code: + # enum: + # - + # - + # examples: + # ExampleKey1: + # value: + # status: + # code: + # message: + # ExampleKey2: + # value: + # status: + # code: + # message: + ####################################################### + ####################################################### + Generic304: + description: Not Modified + headers: + x-correlator: + $ref: '#/components/headers/x-correlator' + content: + application/json: + schema: + title: Generic304 + allOf: + - $ref: '#/components/schemas/ErrorInfo' + - type: object + properties: + status: + enum: [304] + code: + enum: [NOT_MODIFIED] + examples: + GENERIC_304_NOT_MODIFIED: + description: Not Modified. The resource has not been modified since + the last request. + value: + status: 304 + code: NOT_MODIFIED + message: The resource has not been modified since the last request. Generic400: description: Bad Request headers: x-correlator: - $ref: "#/components/headers/x-correlator" + $ref: '#/components/headers/x-correlator' content: application/json: schema: title: Generic400 allOf: - - $ref: "#/components/schemas/ErrorInfo" + - $ref: '#/components/schemas/ErrorInfo' - type: object properties: status: - enum: - - 400 + type: integer + enum: [400] code: - enum: - - INVALID_ARGUMENT - - OUT_OF_RANGE - - "{{SPECIFIC_CODE}}" + type: string + enum: [INVALID_ARGUMENT, OUT_OF_RANGE, '{{SPECIFIC_CODE}}'] examples: GENERIC_400_INVALID_ARGUMENT: description: Invalid Argument. Generic Syntax Exception value: status: 400 code: INVALID_ARGUMENT - message: Client specified an invalid argument, request body or query param. + message: Client specified an invalid argument, request body or query + param. GENERIC_400_OUT_OF_RANGE: - description: Out of Range. Specific Syntax Exception used when a given field has a pre-defined range or a invalid filter criteria combination is requested + description: Out of Range. Specific Syntax Exception used when a given + field has a pre-defined range or an invalid filter criteria combination + is requested value: status: 400 code: OUT_OF_RANGE message: Client specified an invalid range. GENERIC_400_{{SPECIFIC_CODE}}: - description: Specific Syntax Exception regarding a field that is relevant in the context of the API + description: Specific Syntax Exception regarding a field that is relevant + in the context of the API value: status: 400 - code: { { SPECIFIC_CODE } } - message: { { SPECIFIC_CODE_MESSAGE } } - + code: '{{SPECIFIC_CODE}}' + message: '{{SPECIFIC_CODE_MESSAGE}}' Generic401: description: Unauthorized headers: x-correlator: - $ref: "#/components/headers/x-correlator" + $ref: '#/components/headers/x-correlator' content: application/json: schema: title: Generic401 allOf: - - $ref: "#/components/schemas/ErrorInfo" + - $ref: '#/components/schemas/ErrorInfo' - type: object properties: status: - enum: - - 401 + enum: [401] code: - enum: - - UNAUTHENTICATED + enum: [UNAUTHENTICATED, ACCESS_TOKEN_EXPIRED] examples: GENERIC_401_UNAUTHENTICATED: - description: Request cannot be authenticated and a new authentication is required + description: Request cannot be authenticated and a new authentication + is required value: status: 401 code: UNAUTHENTICATED - message: Request not authenticated due to missing, invalid, or expired credentials. A new authentication is required. + message: Request not authenticated due to missing, invalid, or expired + credentials. A new authentication is required. + GENERIC_401_ACCESS_TOKEN_EXPIRED: + description: Request cannot be authenticated and access token expired + value: + status: 401 + code: ACCESS_TOKEN_EXPIRED + message: Request not authenticated due to expired access token. A + new authentication is required. Generic403: description: Forbidden headers: x-correlator: - $ref: "#/components/headers/x-correlator" + $ref: '#/components/headers/x-correlator' content: application/json: schema: title: Generic403 allOf: - - $ref: "#/components/schemas/ErrorInfo" + - $ref: '#/components/schemas/ErrorInfo' - type: object properties: status: - enum: - - 403 + enum: [403] code: - enum: - - PERMISSION_DENIED - - INVALID_TOKEN_CONTEXT - - "{{SPECIFIC_CODE}}" + enum: [PERMISSION_DENIED, INVALID_TOKEN_CONTEXT, '{{SPECIFIC_CODE}}'] examples: GENERIC_403_PERMISSION_DENIED: - description: Permission denied. OAuth2 token access does not have the required scope or when the user fails operational security + description: Permission denied. OAuth2 token access does not have the + required scope or when the user fails operational security value: status: 403 code: PERMISSION_DENIED - message: Client does not have sufficient permissions to perform this action. + message: Client does not have sufficient permissions to perform this + action. GENERIC_403_INVALID_TOKEN_CONTEXT: - description: Reflect some inconsistency between information in some field of the API and the related OAuth2 Token + description: Reflect some inconsistency between information in some + field of the API and the related OAuth2 Token value: status: 403 code: INVALID_TOKEN_CONTEXT - message: "{{field}} is not consistent with access token." + message: '{{field}} is not consistent with access token.' GENERIC_403_{{SPECIFIC_CODE}}: - description: Indicate a Business Logic condition that forbids a process not attached to a specific field in the context of the API + description: Indicate a Business Logic condition that forbids a process + not attached to a specific field in the context of the API value: status: 403 - code: { { SPECIFIC_CODE } } - message: { { SPECIFIC_CODE_MESSAGE } } - + code: '{{SPECIFIC_CODE}}' + message: '{{SPECIFIC_CODE_MESSAGE}}' Generic404: description: Not found headers: x-correlator: - $ref: "#/components/headers/x-correlator" + $ref: '#/components/headers/x-correlator' content: application/json: schema: title: Generic404 allOf: - - $ref: "#/components/schemas/ErrorInfo" + - $ref: '#/components/schemas/ErrorInfo' - type: object properties: status: - enum: - - 404 + enum: [404] code: - enum: - - NOT_FOUND - - IDENTIFIER_NOT_FOUND - - "{{SPECIFIC_CODE}}" + enum: [NOT_FOUND, IDENTIFIER_NOT_FOUND, '{{SPECIFIC_CODE}}'] examples: GENERIC_404_NOT_FOUND: description: Resource is not found @@ -537,32 +567,29 @@ components: code: IDENTIFIER_NOT_FOUND message: Device identifier not found. GENERIC_404_{{SPECIFIC_CODE}}: - description: Specific situation to highlight the resource/concept not found + description: Specific situation to highlight the resource/concept not + found value: status: 404 - code: { { SPECIFIC_CODE } } - message: { { SPECIFIC_CODE_MESSAGE } } - + code: '{{SPECIFIC_CODE}}' + message: '{{SPECIFIC_CODE_MESSAGE}}' GenericDevice404: description: Not found headers: x-correlator: - $ref: "#/components/headers/x-correlator" + $ref: '#/components/headers/x-correlator' content: application/json: schema: title: GenericDevice404 allOf: - - $ref: "#/components/schemas/ErrorInfo" + - $ref: '#/components/schemas/ErrorInfo' - type: object properties: status: - enum: - - 404 + enum: [404] code: - enum: - - NOT_FOUND - - IDENTIFIER_NOT_FOUND + enum: [NOT_FOUND, IDENTIFIER_NOT_FOUND] examples: GENERIC_404_NOT_FOUND: description: Resource is not found @@ -576,83 +603,74 @@ components: status: 404 code: IDENTIFIER_NOT_FOUND message: Device identifier not found. - Generic405: description: Method Not Allowed headers: x-correlator: - $ref: "#/components/headers/x-correlator" + $ref: '#/components/headers/x-correlator' content: application/json: schema: title: Generic405 allOf: - - $ref: "#/components/schemas/ErrorInfo" + - $ref: '#/components/schemas/ErrorInfo' - type: object properties: status: - enum: - - 405 + enum: [405] code: - enum: - - METHOD_NOT_ALLOWED + enum: [METHOD_NOT_ALLOWED] examples: GENERIC_405_METHOD_NOT_ALLOWED: description: Invalid HTTP verb used with a given endpoint value: status: 405 code: METHOD_NOT_ALLOWED - message: The requested method is not allowed/supported on the target resource. - + message: The requested method is not allowed/supported on the target + resource. Generic406: description: Not Acceptable headers: x-correlator: - $ref: "#/components/headers/x-correlator" + $ref: '#/components/headers/x-correlator' content: application/json: schema: title: Generic406 allOf: - - $ref: "#/components/schemas/ErrorInfo" + - $ref: '#/components/schemas/ErrorInfo' - type: object properties: status: - enum: - - 406 + enum: [406] code: - enum: - - NOT_ACCEPTABLE + enum: [NOT_ACCEPTABLE] examples: GENERIC_406_NOT_ACCEPTABLE: - description: API Server does not accept the media type (`Accept-*` header) indicated by API client + description: API Server does not accept the media type (`Accept-*` header) + indicated by API client value: status: 406 code: NOT_ACCEPTABLE - message: The server cannot produce a response matching the content requested by the client through `Accept-*` headers. - + message: The server cannot produce a response matching the content + requested by the client through `Accept-*` headers. Generic409: description: Conflict headers: x-correlator: - $ref: "#/components/headers/x-correlator" + $ref: '#/components/headers/x-correlator' content: application/json: schema: title: Generic409 allOf: - - $ref: "#/components/schemas/ErrorInfo" + - $ref: '#/components/schemas/ErrorInfo' - type: object properties: status: - enum: - - 409 + enum: [409] code: - enum: - - ABORTED - - ALREADY_EXISTS - - CONFLICT - - "{{SPECIFIC_CODE}}" + enum: [ABORTED, ALREADY_EXISTS, CONFLICT, '{{SPECIFIC_CODE}}'] examples: GENERIC_409_ABORTED: description: Concurreny of processes of the same nature/scope @@ -673,116 +691,110 @@ components: code: CONFLICT message: A specified resource duplicate entry found. GENERIC_409_{{SPECIFIC_CODE}}: - description: Specific conflict situation that is relevant in the context of the API + description: Specific conflict situation that is relevant in the context + of the API value: status: 409 - code: { { SPECIFIC_CODE } } - message: { { SPECIFIC_CODE_MESSAGE } } - + code: '{{SPECIFIC_CODE}}' + message: '{{SPECIFIC_CODE_MESSAGE}}' Generic410: description: Gone headers: x-correlator: - $ref: "#/components/headers/x-correlator" + $ref: '#/components/headers/x-correlator' content: application/json: schema: title: Generic410 allOf: - - $ref: "#/components/schemas/ErrorInfo" + - $ref: '#/components/schemas/ErrorInfo' - type: object properties: status: - enum: - - 410 + enum: [410] code: - enum: - - GONE + enum: [GONE] examples: GENERIC_410_GONE: - description: Use in notifications flow to allow API Consumer to indicate that its callback is no longer available + description: Use in notifications flow to allow API Consumer to indicate + that its callback is no longer available value: status: 410 code: GONE message: Access to the target resource is no longer available. - Generic412: description: Failed precondition headers: x-correlator: - $ref: "#/components/headers/x-correlator" + $ref: '#/components/headers/x-correlator' content: application/json: schema: title: Generic412 allOf: - - $ref: "#/components/schemas/ErrorInfo" + - $ref: '#/components/schemas/ErrorInfo' - type: object properties: status: - enum: - - 412 + enum: [412] code: - enum: - - FAILED_PRECONDITION + enum: [FAILED_PRECONDITION] examples: GENERIC_412_FAILED_PRECONDITION: - description: Indication by the API Server that the request cannot be processed in current system state + description: Indication by the API Server that the request cannot be + processed in current system state value: status: 412 code: FAILED_PRECONDITION message: Request cannot be executed in the current system state. - Generic415: description: Unsupported Media Type headers: x-correlator: - $ref: "#/components/headers/x-correlator" + $ref: '#/components/headers/x-correlator' content: application/json: schema: title: Generic415 allOf: - - $ref: "#/components/schemas/ErrorInfo" + - $ref: '#/components/schemas/ErrorInfo' - type: object properties: status: - enum: - - 415 + enum: [415] code: - enum: - - UNSUPPORTED_MEDIA_TYPE + enum: [UNSUPPORTED_MEDIA_TYPE] examples: GENERIC_415_UNSUPPORTED_MEDIA_TYPE: - description: Payload format of the request is in an unsupported format by the Server. Should not happen + description: Payload format of the request is in an unsupported format + by the Server. Should not happen value: status: 415 code: UNSUPPORTED_MEDIA_TYPE - message: The server refuses to accept the request because the payload format is in an unsupported format. - + message: The server refuses to accept the request because the payload + format is in an unsupported format. Generic422: description: Unprocessable Content headers: x-correlator: - $ref: "#/components/headers/x-correlator" + $ref: '#/components/headers/x-correlator' content: application/json: schema: title: Generic422 allOf: - - $ref: "#/components/schemas/ErrorInfo" + - $ref: '#/components/schemas/ErrorInfo' - type: object properties: status: - enum: - - 422 + enum: [422] code: enum: - SERVICE_NOT_APPLICABLE - MISSING_IDENTIFIER - UNSUPPORTED_IDENTIFIER - UNNECESSARY_IDENTIFIER - - "{{SPECIFIC_CODE}}" + - '{{SPECIFIC_CODE}}' examples: GENERIC_422_SERVICE_NOT_APPLICABLE: description: Service not applicable for the provided identifier @@ -791,7 +803,9 @@ components: code: SERVICE_NOT_APPLICABLE message: The service is not available for the provided identifier. GENERIC_422_MISSING_IDENTIFIER: - description: An identifier is not included in the request and the device or phone number identification cannot be derived from the 3-legged access token + description: An identifier is not included in the request and the device + or phone number identification cannot be derived from the 3-legged + access token value: status: 422 code: MISSING_IDENTIFIER @@ -803,38 +817,36 @@ components: code: UNSUPPORTED_IDENTIFIER message: The identifier provided is not supported. GENERIC_422_UNNECESSARY_IDENTIFIER: - description: An explicit identifier is provided when a device or phone number has already been identified from the access token + description: An explicit identifier is provided when a device or phone + number has already been identified from the access token value: status: 422 code: UNNECESSARY_IDENTIFIER message: The device is already identified by the access token. GENERIC_422_{{SPECIFIC_CODE}}: - description: Any semantic condition associated to business logic, specifically related to a field or data structure + description: Any semantic condition associated to business logic, specifically + related to a field or data structure value: status: 422 - code: { { SPECIFIC_CODE } } - message: { { SPECIFIC_CODE_MESSAGE } } - + code: '{{SPECIFIC_CODE}}' + message: '{{SPECIFIC_CODE_MESSAGE}}' Generic429: description: Too Many Requests headers: x-correlator: - $ref: "#/components/headers/x-correlator" + $ref: '#/components/headers/x-correlator' content: application/json: schema: title: Generic429 allOf: - - $ref: "#/components/schemas/ErrorInfo" + - $ref: '#/components/schemas/ErrorInfo' - type: object properties: status: - enum: - - 429 + enum: [429] code: - enum: - - QUOTA_EXCEEDED - - TOO_MANY_REQUESTS + enum: [QUOTA_EXCEEDED, TOO_MANY_REQUESTS] examples: GENERIC_429_QUOTA_EXCEEDED: description: Request is rejected due to exceeding a business quota limit @@ -843,31 +855,29 @@ components: code: QUOTA_EXCEEDED message: Out of resource quota. GENERIC_429_TOO_MANY_REQUESTS: - description: Access to the API has been temporarily blocked due to rate or spike arrest limits being reached + description: Access to the API has been temporarily blocked due to rate + or spike arrest limits being reached value: status: 429 code: TOO_MANY_REQUESTS message: Rate limit reached. - Generic500: description: Internal Server Error headers: x-correlator: - $ref: "#/components/headers/x-correlator" + $ref: '#/components/headers/x-correlator' content: application/json: schema: title: Generic500 allOf: - - $ref: "#/components/schemas/ErrorInfo" + - $ref: '#/components/schemas/ErrorInfo' - type: object properties: status: - enum: - - 500 + enum: [500] code: - enum: - - INTERNAL + enum: [INTERNAL] examples: GENERIC_500_INTERNAL: description: Problem in Server side. Regular Server Exception @@ -875,107 +885,98 @@ components: status: 500 code: INTERNAL message: Unknown server error. Typically a server bug. - Generic501: description: Not Implemented headers: x-correlator: - $ref: "#/components/headers/x-correlator" + $ref: '#/components/headers/x-correlator' content: application/json: schema: title: Generic501 allOf: - - $ref: "#/components/schemas/ErrorInfo" + - $ref: '#/components/schemas/ErrorInfo' - type: object properties: status: - enum: - - 501 + enum: [501] code: - enum: - - NOT_IMPLEMENTED + enum: [NOT_IMPLEMENTED] examples: GENERIC_501_NOT_IMPLEMENTED: - description: Service not implemented. The use of this code should be avoided as far as possible to get the objective to reach aligned implementations + description: Service not implemented. The use of this code should be + avoided as far as possible to get the objective to reach aligned implementations value: status: 501 code: NOT_IMPLEMENTED message: This functionality is not implemented yet. - Generic502: description: Bad Gateway headers: x-correlator: - $ref: "#/components/headers/x-correlator" + $ref: '#/components/headers/x-correlator' content: application/json: schema: title: Generic502 allOf: - - $ref: "#/components/schemas/ErrorInfo" + - $ref: '#/components/schemas/ErrorInfo' - type: object properties: status: - enum: - - 502 + enum: [502] code: - enum: - - BAD_GATEWAY + enum: [BAD_GATEWAY] examples: GENERIC_502_BAD_GATEWAY: - description: Internal routing problem in the Server side that blocks to manage the service properly + description: Internal routing problem in the Server side that blocks + to manage the service properly value: status: 502 code: BAD_GATEWAY message: An upstream internal service cannot be reached. - Generic503: description: Service Unavailable headers: x-correlator: - $ref: "#/components/headers/x-correlator" + $ref: '#/components/headers/x-correlator' content: application/json: schema: title: Generic503 allOf: - - $ref: "#/components/schemas/ErrorInfo" + - $ref: '#/components/schemas/ErrorInfo' - type: object properties: status: - enum: - - 503 + enum: [503] code: - enum: - - UNAVAILABLE + enum: [UNAVAILABLE] examples: GENERIC_503_UNAVAILABLE: - description: Service is not available. Temporary situation usually related to maintenance process in the server side + description: Service is not available. Temporary situation usually related + to maintenance process in the server side value: status: 503 code: UNAVAILABLE message: Service Unavailable. - Generic504: description: Gateway Timeout headers: x-correlator: - $ref: "#/components/headers/x-correlator" + $ref: '#/components/headers/x-correlator' content: application/json: schema: title: Generic504 allOf: - - $ref: "#/components/schemas/ErrorInfo" + - $ref: '#/components/schemas/ErrorInfo' - type: object properties: status: - enum: - - 504 + enum: [504] code: - enum: - - TIMEOUT + enum: [TIMEOUT] examples: GENERIC_504_TIMEOUT: description: API Server Timeout diff --git a/code/API_definitions/camara-service-capability-openapi.yaml b/code/API_definitions/camara-service-capability-openapi.yaml index a3ab30c..c594817 100644 --- a/code/API_definitions/camara-service-capability-openapi.yaml +++ b/code/API_definitions/camara-service-capability-openapi.yaml @@ -1,3 +1,4 @@ +--- openapi: 3.0.3 info: title: CAMARA Service Capability API @@ -47,9 +48,7 @@ info: # Usage The Camara Service Capability API enables clients to discover and manage CAMARA API capabilities through a simple, RESTful interface and receive automatic CloudEvents when state changes. - ```mermaid - Client Webhook/Sink Capability API CloudEvents Broker | | | | |---------------------------------------->| | @@ -69,13 +68,11 @@ info: | |------------------------------------------->| | | 204 | | | | | - The Capability API responds with the supported capabilities and then internally registers for capability change events if 'subscriptionRequest' is provided in the request. As capabilities change event notifications are forwarded through a CloudEvents Broker to the client-provided Webhook (Sink). ``` - **How it works** 1. **Query capabilities** Client sends one or more `CamaraCapabilityQuery` objects to `/camara/service/capability/v0`. @@ -84,36 +81,27 @@ info: 3. **Receive updates automatically** Whenever capability bitmaps or info change, the API emits a CloudEvent (via implicit subscription) to your configured webhook sink endpoint. - **Supported CloudEvent types:** - `org.camaraproject.capability.v0.capability-bitmap-changed` - `org.camaraproject.capability.v0.capability-info-changed` - For full schema definitions and examples, see the components section below. ### Summary: - 1. `POST /camara/service/capability/v0`: Returns tailored CapabilityBitmap that assigns bit positions of each restriction, a mappingVersion for versioning for new restrictions. 2. CloudEvents Notifications: Signals restriction state changes (active/inactive) via bitmap change event and new restrictions via info change event, ensuring efficient synchronization. 3. Versioning: Uses mappingVersion to handle changes in the restriction mapping, preventing synchronization errors. # Relevant terms and definitions - * **Authentication**: Security access keys such as OAuth 2.0 client credentials used by client applications to invoke the Capability API. - * **API (Application Programming Interface)**: A set of protocols and tools for building software and applications. - * **Features**: Specific functions or capabilities of an API that can be *active* or *inactive*. - * **Capabilities**: A collection of features and their status (*active* or *inactive*) at a specific point in time. - * **Footprints**: Define the coverage area where specific capabilities are available. - * **Runtime Restrictions**: Restrictions that affect optional or alternative structures, parameters, and other aspects of API usage using a collection of overlays. There are two kinds of overlays. The openAPI Overlays specification is at https://spec.openapis.org/overlay/latest.html. @@ -123,70 +111,61 @@ info: The actions of any overlays are not known to the Client until they're communicated from the API provider at the runtime of the Client. # API functionality - Please see examples within this yaml on what options the gateway may return in the response. # Further info and support ## Frequently Asked Questions (FAQs) - 1. What is the purpose of the API described in the text? The API enables feature discovery and near-real-time feature status notifications for APIs provided by the gateway. - 2. What are capabilities and how do they relate to API features? Capabilities represent a collection of features and their status (*active* or *inactive*) at a specific point in time. These capabilities provide a way to describe what an API can do. - 3. What are footprints and how do they affect the availability of capabilities? Footprints define the coverage area where specific capabilities are available. A device must be located within the footprint to access these capabilities. If no footprint is specified, the capabilities may be available to any device connected to the network. - 4. What is the role of footprint precedence in the search execution order? Footprint precedence specifies the search execution order of Footprints in the collection. The lower the numerical value of precedence, the higher the Footprint precedence. Footprints with equal precedence may be executed in parallel if supported by the system. - 5. How do runtime restrictions affect API usage? To convey the impact of capability status to API consumers in a meaningful way, capabilities are directly tied to a set of runtime restrictions. These restrictions affect optional or alternative structures, parameters, and other aspects of API usage using a collection of overlays. - 6. What if a Client does not support this API? They can send requests without using this API. The downside is that they may send requests that are invalid and could have been avoided with information from this API. They could be more proactive by disabling / hiding options that are not enabled in the Client which improves user experience. - 7. What if a Client does not support Footprints or a specific Footprint type? They should ignore enforcing the state of the specific capability. This may result in sending invalid requests. - license: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0.html version: wip + x-camara-commonalities: tbd externalDocs: description: Product documentation at Camara url: https://github.com/camaraproject/ servers: - - url: "{apiRoot}" + - url: '{apiRoot}' variables: apiRoot: default: http://localhost:9091 description: API root tags: - name: CAMARA Service Capability Query - description: Returns the Service Capability for specified CAMARA service APIs on the API gateway / producer side. + description: Returns the Service Capability for specified CAMARA service APIs + on the API gateway / producer side. - name: CAMARA Service Capability notifications callback description: Callback endpoint for receiving notifications on capability changes. - paths: /camara/service/capability/v0: post: - tags: - - CAMARA Service Capability Query + tags: [CAMARA Service Capability Query] summary: Retrieve tailored service capabilities based on consumer context description: | Returns service capability information tailored to the consumer's context, including active/inactive restrictions and mapping metadata. @@ -194,35 +173,33 @@ paths: capability identifiers, and a mapping version. It includes response with initial bitmaps which should be enforced on the API consumer side. operationId: postServiceCapability parameters: - - $ref: "#/components/parameters/x-correlator" - - $ref: "#/components/parameters/If-None-Match" - - $ref: "#/components/parameters/If-Modified-Since" + - $ref: '#/components/parameters/x-correlator' + - $ref: '#/components/parameters/If-None-Match' + - $ref: '#/components/parameters/If-Modified-Since' security: - - openId: - - camara-capability:read + - openId: [camara-capability:read] requestBody: required: true content: application/json: schema: - $ref: "#/components/schemas/CamaraCapabilityQueryRequest" + $ref: '#/components/schemas/CamaraCapabilityQueryRequest' examples: CAMARA_CAPABILITY_QUERY_REQUEST_EXAMPLE: - $ref: "#/components/examples/CAMARA_CAPABILITY_QUERY_REQUEST_EXAMPLE" + $ref: '#/components/examples/CAMARA_CAPABILITY_QUERY_REQUEST_EXAMPLE' callbacks: notifications: - "{$request.body#/subscriptionRequest/sink}": + '{$request.body#/subscriptionRequest/sink}': post: - tags: - - CAMARA Service Capability notifications callback - summary: "CAMARA Service Capability notifications callback" + tags: [CAMARA Service Capability notifications callback] + summary: CAMARA Service Capability notifications callback description: | Important: this endpoint is to be implemented by the API consumer. The API provider will call this endpoint whenever any CAMARA Service Capability change related event occurs. Currently only EVENT_CAPABILITY_CHANGED and EVENT_CAPABILITY_REMOVED events are defined. operationId: postCapabilityNotification parameters: - - $ref: "#/components/parameters/x-correlator" + - $ref: '#/components/parameters/x-correlator' requestBody: required: true content: @@ -230,30 +207,30 @@ paths: schema: type: array items: - $ref: "#/components/schemas/CloudEvent" + $ref: '#/components/schemas/CloudEvent' examples: - EVENT_CAPABILITY_BITMAP_CHANGED_EXAMPLE: - $ref: "#/components/examples/EVENT_CAPABILITY_BITMAP_CHANGED_EXAMPLE" - EVENT_CAPABILITY_INFO_CHANGED_EXAMPLE: - $ref: "#/components/examples/EVENT_CAPABILITY_INFO_CHANGED_EXAMPLE" + EVENT_CAPABILITY_BITMAP_CHANGED_BATCH_EXAMPLE: + $ref: '#/components/examples/EVENT_CAPABILITY_BITMAP_CHANGED_BATCH_EXAMPLE' + EVENT_CAPABILITY_INFO_CHANGED_BATCH_EXAMPLE: + $ref: '#/components/examples/EVENT_CAPABILITY_INFO_CHANGED_BATCH_EXAMPLE' responses: - "204": + '204': description: Successful notification headers: x-correlator: $ref: '#/components/headers/x-correlator' - "400": - $ref: "#/components/responses/Generic400" - "401": - $ref: "#/components/responses/Generic401" - "403": - $ref: "#/components/responses/Generic403" - "410": - $ref: "#/components/responses/Generic410" + '400': + $ref: '#/components/responses/Generic400' + '401': + $ref: '#/components/responses/Generic401' + '403': + $ref: '#/components/responses/Generic403' + '410': + $ref: '#/components/responses/Generic410' security: - notificationsBearerAuth: [] responses: - "201": + '201': description: Tailored Capability info with current restriction mapping headers: x-correlator: @@ -267,50 +244,46 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/CapabilityInfo" + $ref: '#/components/schemas/CapabilityInfo' examples: CAMARA_CAPABILITY_QUERY_REQUEST_RESPONSE_EXAMPLE: - $ref: "#/components/examples/CAMARA_CAPABILITY_QUERY_REQUEST_RESPONSE_EXAMPLE" + $ref: '#/components/examples/CAMARA_CAPABILITY_QUERY_REQUEST_RESPONSE_EXAMPLE' '304': - $ref: "#/components/responses/CapabilityNotModified304" - "400": - $ref: "#/components/responses/CapabilityApiBadRequest400" + $ref: '#/components/responses/CapabilityNotModified304' + '400': + $ref: '#/components/responses/CapabilityApiBadRequest400' '401': $ref: '#/components/responses/Generic401' '403': $ref: '#/components/responses/Generic403' - "404": - $ref: "#/components/responses/CapabilityApiNotFound404" + '404': + $ref: '#/components/responses/CapabilityApiNotFound404' '500': $ref: '#/components/responses/Generic500' '503': $ref: '#/components/responses/Generic503' - components: securitySchemes: openId: - $ref: 'CAMARA_common.yaml#/components/securitySchemes/openId' + $ref: CAMARA_common.yaml#/components/securitySchemes/openId notificationsBearerAuth: - $ref: 'CAMARA_common.yaml#/components/securitySchemes/notificationsBearerAuth' - + $ref: CAMARA_common.yaml#/components/securitySchemes/notificationsBearerAuth parameters: x-correlator: - $ref: 'CAMARA_common.yaml#/components/parameters/x-correlator' + $ref: CAMARA_common.yaml#/components/parameters/x-correlator If-None-Match: - $ref: 'CAMARA_common.yaml#/components/parameters/If-None-Match' + $ref: CAMARA_common.yaml#/components/parameters/If-None-Match If-Modified-Since: - $ref: 'CAMARA_common.yaml#/components/parameters/If-Modified-Since' - + $ref: CAMARA_common.yaml#/components/parameters/If-Modified-Since headers: x-correlator: - $ref: 'CAMARA_common.yaml#/components/headers/x-correlator' + $ref: CAMARA_common.yaml#/components/headers/x-correlator Cache-Control: - $ref: 'CAMARA_common.yaml#/components/headers/Cache-Control' + $ref: CAMARA_common.yaml#/components/headers/Cache-Control ETag: - $ref: 'CAMARA_common.yaml#/components/headers/ETag' + $ref: CAMARA_common.yaml#/components/headers/ETag Last-Modified: - $ref: 'CAMARA_common.yaml#/components/headers/Last-Modified' - + $ref: CAMARA_common.yaml#/components/headers/Last-Modified schemas: # General items used throughout the specification Contexts: @@ -326,10 +299,9 @@ components: type: string description: HTTP method in upper-case. request: - $ref: "#/components/schemas/HttpMessage" + $ref: '#/components/schemas/HttpMessage' additionalProperties: true required: [url, method, request] - HttpMessage: type: object description: Common structure for $request and, if supported, $response. @@ -341,11 +313,10 @@ components: A map of HTTP header fields. **Header names (object keys)** SHOULD conform to the RFC-7230 `token` syntax: `^[!#$%&'*+\-\.^_`|~0-9A-Za-z]+$` - Note: OpenAPI 3.0.3 cannot enforce key-name patterns natively. additionalProperties: type: string - pattern: "^[\\t\\x20-\\x7E\\x80-\\xFF]*$" + pattern: ^[\t\x20-\x7E\x80-\xFF]*$ description: Value of the header field (matches `field-value` ABNF) query: type: object @@ -358,47 +329,43 @@ components: body: description: Request or response payload. Its shape depends on Content-Type. additionalProperties: false - VersionedName: description: | An abstract base object containing names with versioning type: object properties: name: - description: The item's name. Ideally, it is a unique value for its type. This value MUST NOT contain the semicolon - ';' + description: The item's name. Ideally, it is a unique value for its type. + This value MUST NOT contain the semicolon - ';' type: string - example: - "cap1" + example: cap1 minLength: 3 maxLength: 256 - pattern: "^[^;]*$" + pattern: ^[^;]*$ version: - description: The version of the object instance. + description: | + The semantic version of the object instance following [SemVer 2.0.0](https://semver.org/). + Examples: + - `1.0.0` + - `2.3.1-beta` + - `1.4.5+build.2025` type: string - example: "0.0.1" + example: 1.0.0 minLength: 1 - pattern: >- - ^(0|[1-9]\d*)\. - (0|[1-9]\d*)\. - (0|[1-9]\d*) - (?:-((?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*) - (?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*))? - (?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$ + pattern: ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$ specifyingBody: description: Entity's specification organization (reversed fqdn format) type: string minLength: 1 required: [name, version] - Footprint: description: | The coverage area to which capabilities apply. They help define the context in which the features are relevant. There are many ways to describe a footprint -- for example, by address range (e.g., IPv4 CIDR or IPv6 CIDR (Classless Inter-Domain Routing), network ID (e.g., Autonomous System Number (ASN)), nation boundaries (e.g., country code) or GPS coordinates. - When a **Footprint** value is not present, the capabilities apply to *any* connected device. allOf: - - $ref: "#/components/schemas/VersionedName" + - $ref: '#/components/schemas/VersionedName' - type: object properties: footprintType: @@ -441,24 +408,27 @@ components: - type: string - type: object footprintUsage: - description: Indicates that the footprint value represents an Access Network, a non Access Network, i.e., networks facing the Internet, or both. + description: Indicates that the footprint value represents an Access + Network, a non Access Network, i.e., networks facing the Internet, + or both. type: string - enum: - - access - - non_access - - both + enum: [access, non_access, both] precedence: description: | Specifies the search execution order of Footprints when they are part of a collection. The lower the numerical value of precedence, the higher the rule precedence. Rules with equal precedence MAY be executed in parallel if supported. type: integer minimum: 0 - required: [name, version, footprintType, footprintValue, footprintUsage, precedence] - + required: + - name + - version + - footprintType + - footprintValue + - footprintUsage + - precedence Metadata: description: > Tighten validation, avoid client/server drift, and make structures robust. - additionalProperties: false # disallow stray/typo properties type: object properties: description: @@ -481,55 +451,54 @@ components: deprecatedAt: type: string format: date-time - description: RFC 3339 timestamp after which this entity is no longer be applicable. + description: RFC 3339 timestamp after which this entity is no longer be + applicable. mappingHash: type: string - pattern: '^[A-Fa-f0-9]{64}$' # SHA-256 in hex - description: SHA-256 digest of the canonical JSON representation of this mapping. - example: '5d41402abc4b2a76b9719d911017c592cf0c58f2b3b65af6f88ab3a2b4d6996f' + pattern: ^[A-Fa-f0-9]{64}$ # SHA-256 in hex + description: SHA-256 digest of the canonical JSON representation of this + mapping. + example: 5d41402abc4b2a76b9719d911017c592cf0c58f2b3b65af6f88ab3a2b4d6996f traceID: type: string description: Trace Identifier used across multiple systems. # Overlay imports Overlay: - $ref: 'overlay-openapi.yaml#/components/schemas/Overlay' + $ref: overlay-openapi.yaml#/components/schemas/Overlay Action: - $ref: 'overlay-openapi.yaml#/components/schemas/Action-Object' + $ref: overlay-openapi.yaml#/components/schemas/Action-Object Extends: - $ref: 'overlay-openapi.yaml#/components/schemas/Extends' + $ref: overlay-openapi.yaml#/components/schemas/Extends # Camara extensions to Open API Overlay components CamaraOverlay: description: | Common attributes of a CAMARA Overlay. It extends OpenAPI Overlay Specification v1.0.0 for restriction-only schema patches. - additionalProperties: false allOf: - - $ref: "#/components/schemas/Overlay" - - $ref: "#/components/schemas/VersionedName" - - $ref: "#/components/schemas/Metadata" + - $ref: '#/components/schemas/Overlay' + - $ref: '#/components/schemas/VersionedName' + - $ref: '#/components/schemas/Metadata' - type: object properties: actions: description: A ordered list of actions type: array minItems: 1 - maxItems: 20 #DoS - guard rail + maxItems: 20 # DoS - guard rail uniqueItems: true items: - $ref: "#/components/schemas/CamaraAction" + $ref: '#/components/schemas/CamaraAction' operator: description: | Logical operator combining the results of all actions: - - **and**: all actions must succeed; processing stops on first failure - **or**: failed actions are skipped type: string enum: [and, or] default: and required: [name, version, actions] - CamaraAction: type: object description: | @@ -538,25 +507,23 @@ components: b. letting the API provider pre-compute exactly which nodes will be affected, using either JSON Pointers or OpenAPI runtime expressions. This makes it possible to: - 1. **target** an OpenAPI document fragment (via JSONPath). 2. **Resolve** that target against an instance of the Open API schema into one or more concrete locations—each expressed as either a JSON Pointer or an OpenAPI runtime expression. 3. **Apply** the `update` or `remove` action deterministically to those resolved locations. - By including `targetLocations`, clients can skip the extra step of evaluating `target` themselves against instances of the schema, ensuring precise, unambiguous application and enabling robust validation through attached `SchemaRestrictions`. When targetLocations is present, any target value MUST be ignored. allOf: - - $ref: "#/components/schemas/Action" + - $ref: '#/components/schemas/Action' properties: id: type: string - description: Identifier for this action. Used for tracability. - Each id MUST be unique within the overlay. + description: Identifier for this action. Used for tracability. Each id MUST + be unique within the overlay. targetLocations: description: | A non-empty list of explicit document locations—specified as a @@ -568,17 +535,19 @@ components: minItems: 1 maxItems: 30 items: - $ref: "#/components/schemas/InstanceLocation" - # ── refinement of update - it can only take on + $ref: '#/components/schemas/InstanceLocation' + # refinement of update - it can only take on update: + description: update of schema restrictions type: object additionalProperties: - $ref: "#/components/schemas/SchemaRestrictions" + $ref: '#/components/schemas/SchemaRestrictions' instanceUpdate: description: An update of an instance document's value. type: object instanceRemove: - description: A boolean indicating the result's value should be removed from the instance's document. + description: A boolean indicating the result's value should be removed from + the instance's document. type: boolean forceAction: type: boolean @@ -589,79 +558,63 @@ components: MUST also be present. default: true example: true - # ── validation logic ────────────────────────────────────────────────── + # validation logic anyOf: # target or targetLocations MUST be present - - required: [target] - - required: [targetLocations] - not: # instanceUpdate and instanceRemove MUST NOT be present at the same time + - required: [target] + - required: [targetLocations] + not: # instanceUpdate and instanceRemove MUST NOT be present at the same time required: [instanceUpdate, instanceRemove] # When forceAction is present, instanceUpdate or instanceRemove MUST be present oneOf: # Case A: forceAction is *not* present (nothing else enforced) - not: - required: [ forceAction ] + required: [forceAction] # Case B: forceAction *is* present, and exactly one payload must accompany it - allOf: - - required: [ forceAction ] + - required: [forceAction] - oneOf: - - required: [ instanceUpdate ] - - required: [ instanceRemove ] - + - required: [instanceUpdate] + - required: [instanceRemove] InstanceLocation: description: | A location in the JSON document that is an instance of an OpenAPI Schema. - It provides an optional endpoint to restrict it as well as the location. - All strings follow a Open API Runtime Expression or JSON Pointer (RFC 6901) format. type: object properties: endpoint: - description: Optional endpoint path of a URI that MUST be present in the request/response. + description: Optional endpoint path of a URI that MUST be present in the + request/response. allOf: - - $ref: "#/components/schemas/InstanceLocationSyntax" + - $ref: '#/components/schemas/InstanceLocationSyntax' location: description: The location of the target result. allOf: - - $ref: "#/components/schemas/InstanceLocationSyntax" + - $ref: '#/components/schemas/InstanceLocationSyntax' additionalProperties: false required: [location] - InstanceLocationSyntax: description: A string whose format is Open API Runtime Expression or JSON Path. type: string minLength: 1 oneOf: - x-camara-targetSyntax: runtimeexpression # runtime expression - pattern: > - ^\$(?:url|method|statusCode - |request\.(?:header\.[!#$%&'*+\-\.\^_`|~0-9A-Za-z]+ - |query\.[^\s\/]+ - |path\.[^\s\/]+ - |body(?:#\/(?:[^\/~]|~0|~1)+(?:\/(?:[^\/~]|~0|~1)+)*)?) - |response\.(?:header\.[!#$%&'*+\-\.\^_`|~0-9A-Za-z]+ - |body(?:#\/(?:[^\/~]|~0|~1)+(?:\/(?:[^\/~]|~0|~1)+)*)?)) + pattern: ^\$(?:url|method|statusCode|request\.(?:header\.[!#$%&'*+\-\.\^_`|~0-9A-Za-z]+|query\.[^\s\/]+|path\.[^\s\/]+|body(?:#\/(?:[^\/~]|~0|~1)+(?:\/(?:[^\/~]|~0|~1)+)*)?)|response\.(?:header\.[!#$%&'*+\-\.\^_`|~0-9A-Za-z]+|body(?:#\/(?:[^\/~]|~0|~1)+(?:\/(?:[^\/~]|~0|~1)+)*)?)) minLength: 1 - - x-camara-targetSyntax: jsonPointer # JSON Pointer - pattern: "^(/([^/~]|~[01])*)*$" + - x-camara-targetSyntax: jsonPointer # JSON Pointer + pattern: ^(/([^/~]|~[01])*)*$ minLength: 1 - SchemaRestrictions: description: | A set of schema constraints evaluated against a single target. - - **restrictions** - An array (min = 1) of `SchemaRestriction` objects. Each restriction returns a Boolean result when applied to the target. - - **operator** - Optional logical operator that combines the restriction results. Supported values are: **and** (default), **or**, **not**. When a single restrictions is supplied, **not** negates that result. - If `operator` is omitted, **and** is assumed. - If only one restriction is present, `operator: not` will negate it. Values of `operator: and` and `operator: or` are ignored. - If `operator` is present, `restrictions` **MUST** also be present. type: object properties: @@ -671,11 +624,10 @@ components: minItems: 1 uniqueItems: true items: - $ref: "#/components/schemas/SchemaRestriction" + $ref: '#/components/schemas/SchemaRestriction' operator: description: | Logical operator that combines the results of all restrictions. - - **and** - All restrictions MUST be true. - **or** - At least one restriction MUST be true. - **not** - No restriction MAY be true. For a single restriction this simply negates the result. @@ -683,138 +635,126 @@ components: enum: [and, or, not] default: and required: [restrictions] - SchemaRestriction: description: | Single schema update that refines and restricts the target. This update **MUST** be compatible with the referenced target. type: object - additionalProperties: false - oneOf: - - $ref: "#/components/schemas/SchemaRestrictionMeta" - - $ref: "#/components/schemas/SchemaRestrictionAnyInstance" - - $ref: "#/components/schemas/SchemaRestrictionNumeric" - - $ref: "#/components/schemas/SchemaRestrictionString" - - $ref: "#/components/schemas/SchemaRestrictionArray" - - $ref: "#/components/schemas/SchemaRestrictionObject" - - $ref: "#/components/schemas/SchemaRestrictionParameter" - - $ref: "#/components/schemas/SchemaRestrictionOperation" - - $ref: "#/components/schemas/SchemaRestrictionPresence" - + anyOf: + - $ref: '#/components/schemas/SchemaRestrictionMeta' + - $ref: '#/components/schemas/SchemaRestrictionAnyInstance' + - $ref: '#/components/schemas/SchemaRestrictionNumeric' + - $ref: '#/components/schemas/SchemaRestrictionString' + - $ref: '#/components/schemas/SchemaRestrictionArray' + - $ref: '#/components/schemas/SchemaRestrictionObject' + - $ref: '#/components/schemas/SchemaRestrictionParameter' + - $ref: '#/components/schemas/SchemaRestrictionOperation' + - $ref: '#/components/schemas/SchemaRestrictionPresence' SchemaRestrictionMeta: type: object description: > Restriction applicable to any target at runtime. - - Based upon the JSON Schema - [A Vocabulary for Basic Meta-Data Annotations](https://www.ietf.org/archive/id/draft-bhutton-json-schema-validation-01.html#name-a-vocabulary-for-basic-meta). + Based upon the JSON Schema [A Vocabulary for Basic Meta-Data Annotations](https://www.ietf.org/archive/id/draft-bhutton-json-schema-validation-01.html#name-a-vocabulary-for-basic-meta). additionalProperties: false properties: - deprecated: { type: boolean, description: "Mark as deprecated." } - readOnly: { type: boolean, description: "Mark as read-only." } - writeOnly: { type: boolean, description: "Mark as write-only." } - default: { type: string, description: "Default value to apply." } - + deprecated: {type: boolean, description: Mark as deprecated.} + readOnly: {type: boolean, description: Mark as read-only.} + writeOnly: {type: boolean, description: Mark as write-only.} + default: {type: string, description: Default value to apply.} SchemaRestrictionAnyInstance: type: object description: > Restriction applicable to any target at runtime. - - Based upon the JSON Schema - [Validation keywords for Any instances](https://www.ietf.org/archive/id/draft-bhutton-json-schema-validation-01.html#name-validation-keywords-for-any). + Based upon the JSON Schema [Validation keywords for Any instances](https://www.ietf.org/archive/id/draft-bhutton-json-schema-validation-01.html#name-validation-keywords-for-any). additionalProperties: false properties: type: type: string - enum: [null, boolean, object, array, number, string, integer] + enum: [boolean, object, array, number, string, integer] + nullable: true description: > Restrict the type of the value. Only applicable when the type was not initially specified or matches the target's current type. enum: type: array - items: { type: string } - description: "Restrict allowed values (must be a subset of the original enum)." + items: {type: string} + description: Restrict allowed values (must be a subset of the original enum). const: type: string - description: "Force the field to have a constant value." - + description: Force the field to have a constant value. SchemaRestrictionNumeric: type: object description: > Restriction applicable to numeric ranges (for example min/max values). - - Based upon the JSON Schema - [Validation keywords for Numeric Instances](https://www.ietf.org/archive/id/draft-bhutton-json-schema-validation-01.html#name-validation-keywords-for-num). + Based upon the JSON Schema [Validation keywords for Numeric Instances](https://www.ietf.org/archive/id/draft-bhutton-json-schema-validation-01.html#name-validation-keywords-for-num). additionalProperties: false properties: - multipleOf: { type: number, minimum: 1, description: "Value MUST be a multiple of this number." } - maximum: { type: number, description: "Value MUST be less than or equal to this number." } - minimum: { type: number, description: "Value MUST be greater than or equal to this number." } - exclusiveMaximum: { type: number, description: "Value MUST be strictly less than this number." } - exclusiveMinimum: { type: number, description: "Value MUST be strictly greater than this number." } - + multipleOf: {type: number, minimum: 1, description: Value MUST be a multiple + of this number.} + maximum: {type: number, description: Value MUST be less than or equal to this + number.} + minimum: {type: number, description: Value MUST be greater than or equal to + this number.} + exclusiveMaximum: {type: number, description: Value MUST be strictly less + than this number.} + exclusiveMinimum: {type: number, description: Value MUST be strictly greater + than this number.} SchemaRestrictionString: type: object description: > Restriction applicable to string fields (length or pattern). - - Based upon the JSON Schema - [Validation keywords for Strings](https://www.ietf.org/archive/id/draft-bhutton-json-schema-validation-01.html#name-validation-keywords-for-str). + Based upon the JSON Schema [Validation keywords for Strings](https://www.ietf.org/archive/id/draft-bhutton-json-schema-validation-01.html#name-validation-keywords-for-str). additionalProperties: false properties: - maxLength: { type: integer, minimum: 0, description: "Maximum string length." } - minLength: { type: integer, minimum: 0, description: "Minimum string length." } - pattern: { type: string, description: "Regular-expression pattern the string MUST match." } - + maxLength: {type: integer, minimum: 0, description: Maximum string length.} + minLength: {type: integer, minimum: 0, description: Minimum string length.} + pattern: {type: string, description: Regular-expression pattern the string + MUST match.} SchemaRestrictionArray: type: object description: > Restriction applicable to arrays (size or uniqueness). - - Based upon the JSON Schema - [Validation keywords for Array Instances](https://www.ietf.org/archive/id/draft-bhutton-json-schema-validation-01.html#name-validation-keywords-for-arr). + Based upon the JSON Schema [Validation keywords for Array Instances](https://www.ietf.org/archive/id/draft-bhutton-json-schema-validation-01.html#name-validation-keywords-for-arr). additionalProperties: false properties: - maxItems: { type: integer, minimum: 0, description: "Maximum number of items." } - minItems: { type: integer, minimum: 0, description: "Minimum number of items." } - uniqueItems: { type: boolean, description: "If **true**, all items MUST be unique." } - maxContains: { type: integer, minimum: 0, description: "Maximum count for items that match the `contains` schema." } - minContains: { type: integer, minimum: 0, description: "Minimum count for items that match the `contains` schema." } - + maxItems: {type: integer, minimum: 0, description: Maximum number of items.} + minItems: {type: integer, minimum: 0, description: Minimum number of items.} + uniqueItems: {type: boolean, description: 'If **true**, all items MUST be + unique.'} + maxContains: {type: integer, minimum: 0, description: Maximum count for items + that match the `contains` schema.} + minContains: {type: integer, minimum: 0, description: Minimum count for items + that match the `contains` schema.} SchemaRestrictionObject: type: object description: > Restriction applicable to object structures. - - Based upon the JSON Schema - [Validation keywords for Object Instances](https://www.ietf.org/archive/id/draft-bhutton-json-schema-validation-01.html#name-validation-keywords-for-obj). + Based upon the JSON Schema [Validation keywords for Object Instances](https://www.ietf.org/archive/id/draft-bhutton-json-schema-validation-01.html#name-validation-keywords-for-obj). additionalProperties: false properties: - maxProperties: { type: integer, minimum: 0, description: "Maximum number of object properties." } - minProperties: { type: integer, minimum: 0, description: "Minimum number of object properties." } + maxProperties: {type: integer, minimum: 0, description: Maximum number of + object properties.} + minProperties: {type: integer, minimum: 0, description: Minimum number of + object properties.} required: type: array - items: { type: string } - description: "List of required properties (MUST already exist in the schema)." + items: {type: string} + description: List of required properties (MUST already exist in the schema). dependentRequired: type: array - items: { type: string } - description: "[`dependentRequired`](https://json-schema.org/draft/2020-12/json-schema-validation#name-validation-keywords-for-obj)" + items: {type: string} + description: '[`dependentRequired`](https://json-schema.org/draft/2020-12/json-schema-validation#name-validation-keywords-for-obj)' excludedProperties: type: array - items: { type: string } - description: "Properties that MUST be absent." - + items: {type: string} + description: Properties that MUST be absent. SchemaRestrictionParameter: type: object description: > Restriction that applies only to HTTP request parameters (e.g. query parameters). - Based upon the OpenAPI *Parameter Object* and provides: - - - Mandating the use of an optional parameter - - Allowing empty values + - Mandating the use of an optional parameter - Allowing empty values additionalProperties: false properties: allowEmptyValue: @@ -826,94 +766,88 @@ components: type: boolean description: > Mandates the use of an otherwise-optional parameter. Allowed only - when: - 1. The original schema does **not** declare `deprecated: true`, and - 2. The original schema does **not** set `mandatory` to the opposite value. - + when: 1. The original schema does **not** declare `deprecated: true`, + and 2. The original schema does **not** set `mandatory` to the opposite + value. SchemaRestrictionOperation: type: object description: > Restriction that applies to an absolute or relative path (operation). - Based upon the OpenAPI *Operation Object* and provides: - - - `notImplemented` - - `notAvailable` + - `notImplemented` - `notAvailable` additionalProperties: false properties: notImplemented: type: boolean - description: "Marks the operation as unimplemented. Invocation MUST return **501 Not Implemented**." + description: Marks the operation as unimplemented. Invocation MUST return + **501 Not Implemented**. notAvailable: type: boolean - description: "Marks the operation as temporarily unavailable. Invocation MUST return **503 Service Unavailable**." - + description: Marks the operation as temporarily unavailable. Invocation + MUST return **503 Service Unavailable**. SchemaRestrictionPresence: type: object description: > Restriction that applies to runtime presence of the target. - additionalProperties: false properties: presence: type: boolean description: > When **true**, at least one instance matching the target JSON Pointer - or JSON Path **MUST** be present. - When **false**, no such instance **MAY** be present. - + or JSON Path **MUST** be present. When **false**, no such instance **MAY** + be present. SchemaRestrictionsSet: description: Base restriction type type: object - additionalProperties: false # disallow stray/typo properties allOf: - - $ref: "#/components/schemas/VersionedName" + - $ref: '#/components/schemas/VersionedName' properties: restrictions: + description: restrictions type: array uniqueItems: true minItems: 1 maxItems: 10 items: - $ref: "#/components/schemas/CamaraOverlay" + $ref: '#/components/schemas/CamaraOverlay' footprints: + description: footprints type: array uniqueItems: true minItems: 1 maxItems: 10 items: - $ref: "#/components/schemas/Footprint" + $ref: '#/components/schemas/Footprint' resourceServers: + description: resourceServers type: array - uniqueItems: true # no duplicates + uniqueItems: true # no duplicates maxItems: 10 items: type: string - format: uri # ensures each locator is a valid URI + format: uri # ensures each locator is a valid URI required: [restrictions] # Camara capability structures CapabilityBitmap: description: Common attributes of CAMARA capability bitmap type: object - additionalProperties: false allOf: - - $ref: "#/components/schemas/CamaraCapabilityQuery" + - $ref: '#/components/schemas/CamaraCapabilityQuery' properties: mappingVersion: type: string - description: Version of the capability to restriction mapping, used to detect changes. - example: "1.0.0" + description: Version of the capability to restriction mapping, used to detect + changes. + example: 1.0.0 camaraCapabilitiesBitmap: description: | Bitmap value of the capabilities to show current state (active or inactive) of the RestrictionSet. - Decimal representation of a binary bitmask indicating active capabilities. This integer should be interpreted as a binary string (bitfield), where: - - The **least significant bit (rightmost bit)** corresponds to key **"0"** in the `bitmapCapabilities` object. - The next bit to the left corresponds to key **"1"**, and so on. - Bit at position `n` (counting from right, 0-based) maps to key `"n"`. - For example: - If `CapabilityBitmap` = `13`, the binary form is `1101`. - Interpreted as: @@ -922,7 +856,6 @@ components: - Bit 2 → "2" → active - Bit 3 (MSB) → "3" → active - This means `bitmapCapabilities["0"]`, `["2"]`, and `["3"]` apply. - Implementors of API provider should preserve this bit order when interpreting or generating the bitmask, so that capability indices remain consistent over time. type: integer minimum: 0 @@ -930,77 +863,69 @@ components: maximum: 18446744073709551615 example: 6 required: [mappingVersion, camaraCapabilitiesBitmap] - CapabilityInfo: description: A list of CapabilityDetail. type: object - additionalProperties: false properties: details: description: a list of CapabilityDetail. type: array minItems: 1 - maxItems: 1000 #DoS guard rail + maxItems: 1000 # DoS guard rail uniqueItems: true items: - $ref: "#/components/schemas/CapabilityDetail" - + $ref: '#/components/schemas/CapabilityDetail' CapabilityDetail: description: | A self-contained snapshot of what each capability means (CapabilityBitmap) and its current active/inactive state. When these are CapabilitySetFootprint the state is always active. - When it is CapabilitySetBitmap, then CapabilityBitmap is included that conveys the active/inactive state of each bit position. type: object - additionalProperties: false - oneOf: - - $ref: "#/components/schemas/CapabilitySetFootprint" + anyOf: + - $ref: '#/components/schemas/CapabilitySetFootprint' - allOf: - - $ref: "#/components/schemas/CapabilitySetBitmap" - - $ref: "#/components/schemas/CapabilityBitmap" + - $ref: '#/components/schemas/CapabilitySetBitmap' + - $ref: '#/components/schemas/CapabilityBitmap' minProperties: 1 - CapabilitySetFootprint: description: | Associates a capability with one or more RestrictionSets that defined by footprint constraints. type: object - additionalProperties: false # reject typos / undocumented fields + additionalProperties: false # reject typos / undocumented fields allOf: - - $ref: "#/components/schemas/VersionedName" - - $ref: "#/components/schemas/Metadata" + - $ref: '#/components/schemas/VersionedName' + - $ref: '#/components/schemas/Metadata' properties: footprints: - description: An array of restrictions that apply when the endpoint is present in one of - the entry's footprints. + description: An array of restrictions that apply when the endpoint is present + in one of the entry's footprints. type: array minItems: 1 maxItems: 64 uniqueItems: true items: allOf: - - $ref: "#/components/schemas/SchemaRestrictionsSet" + - $ref: '#/components/schemas/SchemaRestrictionsSet' - required: [footprints] required: [footprints] - CapabilitySetBitmap: description: | Associates a capability with one or more RestrictionSets define through a bitmap position. type: object - additionalProperties: false # reject typos / undocumented fields allOf: - - $ref: "#/components/schemas/VersionedName" - - $ref: "#/components/schemas/Metadata" + - $ref: '#/components/schemas/VersionedName' + - $ref: '#/components/schemas/Metadata' properties: bitmapCapabilities: type: object description: > - Map of bitPosition → SchemaRestrictionsSet. - Keys are stringified bitPosition indices (duplicates impossible). - **Header names (object keys)** SHOULD consist of one or more digits, matching `^[0-9]+$`. - (Note: OpenAPI 3.0.3 cannot enforce key-name patterns natively.) + Map of bitPosition → SchemaRestrictionsSet. Keys are stringified bitPosition + indices (duplicates impossible). **Header names (object keys)** SHOULD + consist of one or more digits, matching `^[0-9]+$`. (Note: OpenAPI 3.0.3 + cannot enforce key-name patterns natively.) additionalProperties: $ref: '#/components/schemas/SchemaRestrictionsSet' required: [bitmapCapabilities] @@ -1015,136 +940,117 @@ components: description: A list of CamaraCapabilityQuery type: array minItems: 1 - maxItems: 100 #DoS guard rail + maxItems: 100 # DoS guard rail uniqueItems: true items: - $ref: "#/components/schemas/CamaraCapabilityQuery" + $ref: '#/components/schemas/CamaraCapabilityQuery' subscriptionRequest: - $ref: "#/components/schemas/CamaraExtendedSubscriptionRequest" + $ref: '#/components/schemas/CamaraExtendedSubscriptionRequest' required: [queries] - CamaraCapabilityQuery: description: Common attributes of CAMARA capability query type: object - additionalProperties: false properties: - device: - $ref: "#/components/schemas/Device" + resourceScopes: + $ref: '#/components/schemas/ResourceScopes' overlayExtends: description: list of unique overlay extends in the query type: array minItems: 1 - maxItems: 20 #DoS guard rail + maxItems: 20 # DoS guard rail uniqueItems: true items: - $ref: "#/components/schemas/Extends" + $ref: '#/components/schemas/Extends' required: [overlayExtends] - - Device: - $ref: "CAMARA_common.yaml#/components/schemas/Device" - + ResourceScopes: + $ref: CAMARA_common.yaml#/components/schemas/ResourceScopes ErrorInfo: - $ref: 'CAMARA_common.yaml#/components/schemas/ErrorInfo' + $ref: CAMARA_common.yaml#/components/schemas/ErrorInfo # Event structures CamaraExtendedSubscriptionRequest: - $ref: 'CAMARA-subscriptions-openapi.yaml#/components/schemas/CamaraExtendedSubscriptionRequest' - + $ref: CAMARA-subscriptions-openapi.yaml#/components/schemas/CamaraExtendedSubscriptionRequest org.camaraproject.capability.v0.detail: description: The detail of the requested capability event subscription. type: object allOf: - - $ref: 'CAMARA-subscriptions-openapi.yaml#/components/schemas/SubscriptionDetail' + - $ref: CAMARA-subscriptions-openapi.yaml#/components/schemas/SubscriptionDetail - type: object properties: - device: - $ref: "#/components/schemas/Device" + resourceScopes: + $ref: '#/components/schemas/ResourceScopes' additionalProperties: false - CloudEvent: - $ref: 'CAMARA-subscriptions-openapi.yaml#/components/schemas/CamaraExtendedCloudEventsAttribute' - + $ref: CAMARA-subscriptions-openapi.yaml#/components/schemas/CamaraExtendedCloudEventsAttribute CloudEventData: - $ref: 'CAMARA-subscriptions-openapi.yaml#/components/schemas/CamaraCloudEventData' - + $ref: CAMARA-subscriptions-openapi.yaml#/components/schemas/CamaraCloudEventData org.camaraproject.capability.v0.capability-bitmap-changed: description: Event structure for capability bitmap changed allOf: - - $ref: "#/components/schemas/CloudEvent" + - $ref: '#/components/schemas/CloudEvent' - type: object properties: data: - $ref: "#/components/schemas/org.camaraproject.capability.v0.capability-bitmap-changed.data" - required: - - data + $ref: '#/components/schemas/org.camaraproject.capability.v0.capability-bitmap-changed.data' + required: [data] additionalProperties: false example: - $ref: "#/components/examples/EVENT_CAPABILITY_BITMAP_CHANGED_EXAMPLE/value" - + $ref: '#/components/examples/EVENT_CAPABILITY_BITMAP_CHANGED_EXAMPLE/value' org.camaraproject.capability.v0.capability-bitmap-changed.data: description: Event for capability bitmap changed allOf: - - $ref: "#/components/schemas/CloudEventData" + - $ref: '#/components/schemas/CloudEventData' - type: object properties: capabilityBitmap: - $ref: "#/components/schemas/CapabilityBitmap" - required: - - capabilityBitmap + $ref: '#/components/schemas/CapabilityBitmap' + required: [capabilityBitmap] additionalProperties: false - org.camaraproject.capability.v0.capability-info-changed: description: Event structure for capability info changed allOf: - - $ref: "#/components/schemas/CloudEvent" + - $ref: '#/components/schemas/CloudEvent' - type: object properties: data: - $ref: "#/components/schemas/org.camaraproject.capability.v0.capability-info-changed.data" - required: - - data + $ref: '#/components/schemas/org.camaraproject.capability.v0.capability-info-changed.data' + required: [data] additionalProperties: false example: - $ref: "#/components/examples/EVENT_CAPABILITY_INFO_CHANGED_EXAMPLE/value" - + $ref: '#/components/examples/EVENT_CAPABILITY_INFO_CHANGED_EXAMPLE/value' org.camaraproject.capability.v0.capability-info-changed.data: description: Event for capability info changed allOf: - - $ref: "#/components/schemas/CloudEventData" + - $ref: '#/components/schemas/CloudEventData' - type: object properties: capabilityInfo: - $ref: "#/components/schemas/CapabilityInfo" - required: - - capabilityInfo + $ref: '#/components/schemas/CapabilityInfo' + required: [capabilityInfo] additionalProperties: false - responses: CapabilityNotModified304: description: Not Modified (cached response) headers: x-correlator: - $ref: "#/components/headers/x-correlator" - + $ref: '#/components/headers/x-correlator' Generic400: - $ref: "CAMARA_common.yaml#/components/responses/Generic400" - + $ref: CAMARA_common.yaml#/components/responses/Generic400 CapabilityApiBadRequest400: description: Bad Request when query capability headers: x-correlator: - $ref: "#/components/headers/x-correlator" + $ref: '#/components/headers/x-correlator' content: application/json: schema: title: CapabilityApiBadRequest400 allOf: - - $ref: "#/components/schemas/ErrorInfo" + - $ref: '#/components/schemas/ErrorInfo' - type: object properties: status: - enum: - - 400 + enum: [400] code: enum: - INVALID_ARGUMENT @@ -1157,9 +1063,12 @@ components: value: status: 400 code: INVALID_ARGUMENT - message: Client specified an invalid argument, request body or query param. + message: Client specified an invalid argument, request body or query + param. GENERIC_400_OUT_OF_RANGE: - description: Out of Range. Specific Syntax Exception used when a given field has a pre-defined range or a invalid filter criteria combination is requested + description: Out of Range. Specific Syntax Exception used when a given + field has a pre-defined range or a invalid filter criteria combination + is requested value: status: 400 code: OUT_OF_RANGE @@ -1174,16 +1083,12 @@ components: status: 400 code: INVALID_TOKEN message: Only bearer token is supported - Generic401: - $ref: "CAMARA_common.yaml#/components/responses/Generic401" - + $ref: CAMARA_common.yaml#/components/responses/Generic401 Generic403: - $ref: "CAMARA_common.yaml#/components/responses/Generic403" - + $ref: CAMARA_common.yaml#/components/responses/Generic403 Generic404: - $ref: "CAMARA_common.yaml#/components/responses/Generic404" - + $ref: CAMARA_common.yaml#/components/responses/Generic404 CapabilityApiNotFound404: description: Capability API not found content: @@ -1191,228 +1096,278 @@ components: schema: title: CapabilityApiNotFound404 allOf: - - $ref: "#/components/schemas/ErrorInfo" + - $ref: '#/components/schemas/ErrorInfo' - type: object properties: status: - enum: - - 404 + enum: [404] code: - enum: - - NOT_FOUND + enum: [NOT_FOUND] example: status: 404 code: NOT_FOUND - message: "No Capability API found" - + message: No Capability API found Generic409: - $ref: "CAMARA_common.yaml#/components/responses/Generic409" - + $ref: CAMARA_common.yaml#/components/responses/Generic409 Generic410: - $ref: "CAMARA_common.yaml#/components/responses/Generic410" - + $ref: CAMARA_common.yaml#/components/responses/Generic410 Generic429: - $ref: "CAMARA_common.yaml#/components/responses/Generic429" - + $ref: CAMARA_common.yaml#/components/responses/Generic429 Generic500: - $ref: "CAMARA_common.yaml#/components/responses/Generic500" - + $ref: CAMARA_common.yaml#/components/responses/Generic500 Generic503: - $ref: "CAMARA_common.yaml#/components/responses/Generic503" - + $ref: CAMARA_common.yaml#/components/responses/Generic503 examples: CAMARA_CAPABILITY_QUERY_REQUEST_EXAMPLE: summary: Example of capability query description: query capability request value: queries: - - device: - phoneNumber: "+123456788" + - resourceScopes: + - phoneNumber: '+123456788' overlayExtends: - - "https://github.com/camaraproject/QualityOnDemand/blob/r2.2/code/API_definitions/quality-on-demand.yaml" - - "https://github.com/camaraproject/QualityOnDemand/blob/r2.2/code/API_definitions/qos-profiles.yaml" + - https://github.com/camaraproject/QualityOnDemand/blob/r2.2/code/API_definitions/quality-on-demand.yaml + - https://github.com/camaraproject/QualityOnDemand/blob/r2.2/code/API_definitions/qos-profiles.yaml subscriptionRequest: - sink: "https://application-server.com/notifications" - protocol: "HTTP" + sink: https://application-server.com/notifications + protocol: HTTP types: - - "org.camaraproject.capability.v0.capability-info-changed" - - "org.camaraproject.capability.v0.capability-bitmap-changed" + - org.camaraproject.capability.v0.capability-info-changed + - org.camaraproject.capability.v0.capability-bitmap-changed config: subscriptionDetail: - device: - phoneNumber: "+123456788" - + resourceScopes: + - phoneNumber: '+123456788' CAMARA_CAPABILITY_QUERY_REQUEST_RESPONSE_EXAMPLE: summary: Example of capability query response description: query capability response value: details: - name: cap-qod-adi - version: "0.0.1" - createdAt: "2025-05-09T14:25:38Z" + version: 1.0.1 + createdAt: '2025-05-09T14:25:38Z' overlayExtends: - https://github.com/camaraproject/QualityOnDemand/blob/r2.2/code/API_definitions/quality-on-demand.yaml - https://github.com/camaraproject/QualityOnDemand/blob/r2.2/code/API_definitions/qos-profiles.yaml - device: - phoneNumber: "+123456788" - mappingVersion: "1.0.0" + resourceScopes: + - phoneNumber: '+123456788' + mappingVersion: 1.0.0 camaraCapabilitiesBitmap: 63 bitmapCapabilities: - "0": + '0': name: rr-qod-adi - version: "0.0.1" + version: 1.0.1 restrictions: - name: org.camaraproject.capability.v0.object-instance-restriction.accepted-device-identifiers - version: "0.0.1" + version: 0.0.1 extends: https://github.com/camaraproject/QualityOnDemand/blob/r2.2/code/API_definitions/quality-on-demand.yaml actions: - - target: "$.components.schemas['Device'].properties['ipv4Address']" + - target: $.components.schemas['Device'].properties['ipv4Address'] remove: true - - target: "$.components.schemas['Device'].properties['networkAccessIdentifier']" + - target: $.components.schemas['Device'].properties['networkAccessIdentifier'] remove: true - "1": + '1': name: rr-qod-xcor - version: "0.0.1" + version: 1.0.1 restrictions: - name: org.camaraproject.capability.v0.parameter-restriction.x-cor-required - version: "0.0.1" + version: 0.0.1 extends: https://github.com/camaraproject/QualityOnDemand/blob/r2.2/code/API_definitions/quality-on-demand.yaml actions: - - target: "$.components.parameters['x-correlator']" + - target: $.components.parameters['x-correlator'] update: - - mandatory: true - "2": + xcor-required: + restrictions: + - mandatory: true + '2': name: rr-session-extend-unavailable - version: "0.0.1" + version: 1.0.1 restrictions: - name: org.camaraproject.capability.v0.operation-restriction.session-extend-unavailable - version: "0.0.1" + version: 0.0.1 extends: https://github.com/camaraproject/QualityOnDemand/blob/r2.2/code/API_definitions/quality-on-demand.yaml actions: - - target: "$.paths['/sessions/{sessionId}/extend'].post" - targetLocations: - - location: "/paths/~1sessions~1{sessionId}~1extend/post" + - target: $.paths['/sessions/{sessionId}/extend'].post update: - - notAvailable: true - "3": + session-extend-unavailable: + restrictions: + - notAvailable: true + '3': name: rr-session-accept-qos - version: "0.0.1" + version: 1.0.1 restrictions: - name: org.camaraproject.capability.v0.enum-restriction.accepted-qos-profiles - version: "0.0.1" + version: 0.0.1 extends: https://github.com/camaraproject/QualityOnDemand/blob/r2.2/code/API_definitions/quality-on-demand.yaml operator: and actions: - targetLocations: - - location: "$method" + - location: $method update: - - enum: - - "POST" + accepted-qos-profiles: + restrictions: + - enum: [POST] - targetLocations: - - location: "$request.path" + - location: $request.path.sessionId update: - - enum: - - "/sessions" + accepted-qos-profiles: + restrictions: + - enum: [/sessions] - targetLocations: - - location: "$request.body#/qosProfile" + - location: $request.body#/qosProfile update: - - enum: - - "QoS_XR" - - "QoS_VC" - "4": + accepted-qos-profiles: + restrictions: + - enum: [QoS_XR, QoS_VC] + '4': name: rr-ipv6-portspec-max-5 - version: "0.0.1" + version: 1.0.1 restrictions: - name: org.camaraproject.capability.v0.object-instance-restriction.appserv-ipv6 - version: "0.0.1" + version: 1.0.1 extends: https://github.com/camaraproject/QualityOnDemand/blob/r2.2/code/API_definitions/quality-on-demand.yaml actions: - - target: "$.components.schemas['ApplicationServer'].properties['ipv4Address']" + - target: $.components.schemas['ApplicationServer'].properties['ipv4Address'] remove: true - name: org.camaraproject.capability.v0.array-size-restriction.portspec-ports-max5 - version: "0.0.1" + version: 1.0.1 extends: https://github.com/camaraproject/QualityOnDemand/blob/r2.2/code/API_definitions/quality-on-demand.yaml actions: - - target: "$.components.schemas['PortsSpec'].properties['ports']" + - target: $.components.schemas['PortsSpec'].properties['ports'] update: - - maxItems: 5 - - "5": + portspec-ports-max5: + restrictions: + - maxItems: 5 + '5': name: rr-sessioninfo-duration-multipleof-60 - version: "0.0.1" + version: 1.0.1 restrictions: - name: org.camaraproject.capability.v0.numeric-restriction.sessioninfo-duration-min60-multiple60 - version: "0.0.1" + version: 1.0.1 extends: https://github.com/camaraproject/QualityOnDemand/blob/r2.2/code/API_definitions/quality-on-demand.yaml actions: - - target: "$.components.schemas['SessionInfo'].properties['duration']" + - target: $.components.schemas['SessionInfo'].properties['duration'] update: - - minimum: 60 - - multipleOf: 60 - "6": + sessioninfo-duration-min60-multiple60: + restrictions: + - minimum: 60 + - multipleOf: 60 + '6': name: rr-qosprofile-get-unavailable - version: "0.0.1" + version: 1.0.1 restrictions: - name: org.camaraproject.capability.v0.operation-restriction.qosprofile-get-unavailable - version: "0.0.1" + version: 1.0.1 extends: https://github.com/camaraproject/QualityOnDemand/blob/r2.2/code/API_definitions/qos-profiles.yaml actions: - - target: "$.paths['/qos-profiles/{name}'].get" + - target: $.paths['/qos-profiles/{name}'].get remove: true - EVENT_CAPABILITY_BITMAP_CHANGED_EXAMPLE: - summary: Cloud event example for capability bitmap changed + summary: Cloud event example for capability bitmap changed description: Cloud event example for capability bitmap changed value: id: cb1 source: https://api.example.com/capability/capability-subscriptions/bitmap - datacontenttype: "application/json" - specversion: "1.0" + datacontenttype: application/json + specversion: '1.0' type: org.camaraproject.capability.v0.capability-bitmap-changed - time: "2025-05-06T00:00:00.000Z" + time: '2025-05-06T00:00:00.000Z' data: capabilityBitmap: - device: - phoneNumber: "+123456788" + resourceScopes: + - phoneNumber: '+123456788' overlayExtends: - https://github.com/camaraproject/QualityOnDemand/blob/r2.2/code/API_definitions/quality-on-demand.yaml - https://github.com/camaraproject/QualityOnDemand/blob/r2.2/code/API_definitions/qos-profiles.yaml - mappingVersion: "1.0.0" + mappingVersion: 1.0.0 camaraCapabilitiesBitmap: 127 - - + EVENT_CAPABILITY_BITMAP_CHANGED_BATCH_EXAMPLE: + summary: Batch (single item) - capability bitmap changed + description: Cloud event batch example for capability bitmap changed + value: + - id: cb1 + source: https://api.example.com/capability/capability-subscriptions/bitmap + datacontenttype: application/json + specversion: '1.0' + type: org.camaraproject.capability.v0.capability-bitmap-changed + time: '2025-05-06T00:00:00.000Z' + data: + capabilityBitmap: + resourceScopes: + - phoneNumber: '+123456788' + overlayExtends: + - https://github.com/camaraproject/QualityOnDemand/blob/r2.2/code/API_definitions/quality-on-demand.yaml + - https://github.com/camaraproject/QualityOnDemand/blob/r2.2/code/API_definitions/qos-profiles.yaml + mappingVersion: 1.0.0 + camaraCapabilitiesBitmap: 127 EVENT_CAPABILITY_INFO_CHANGED_EXAMPLE: description: Cloud event example for capability info changed value: id: ci1 source: https://api.example.com/capability/capability-subscriptions/info - specversion: "1.0" - datacontenttype: "application/json" + specversion: '1.0' + datacontenttype: application/json type: org.camaraproject.capability.v0.capability-info-changed - time: "2025-05-06T00:00:00.000Z" + time: '2025-05-06T00:00:00.000Z' data: capabilityInfo: details: - name: cap-qod-adi - version: "0.0.2" - createdAt: "2025-05-09T14:25:38Z" + version: 1.0.2 + createdAt: '2025-05-09T14:25:38Z' overlayExtends: - https://github.com/camaraproject/QualityOnDemand/blob/r2.2/code/API_definitions/quality-on-demand.yaml - https://github.com/camaraproject/QualityOnDemand/blob/r2.2/code/API_definitions/qos-profiles.yaml - device: - phoneNumber: "+123456788" - mappingVersion: "1.0.0" + resourceScopes: + - phoneNumber: '+123456788' + mappingVersion: 1.0.0 camaraCapabilitiesBitmap: 1 bitmapCapabilities: - "0": + '0': name: rr-qod-adi - version: "0.0.1" + version: 1.0.1 restrictions: - name: org.camaraproject.capability.v0.object-instance-restriction.accepted-device-identifiers - version: "0.0.1" + version: 1.0.1 extends: https://github.com/camaraproject/QualityOnDemand/blob/r2.2/code/API_definitions/quality-on-demand.yaml actions: - - target: "$.components.schemas['Device'].properties['ipv4Address']" + - target: $.components.schemas['Device'].properties['ipv4Address'] remove: true - - target: "$.components.schemas['Device'].properties['networkAccessIdentifier']" + - target: $.components.schemas['Device'].properties['networkAccessIdentifier'] remove: true + EVENT_CAPABILITY_INFO_CHANGED_BATCH_EXAMPLE: + summary: Batch (single item) - capability info changed + description: Cloud event batch example for capability info changed + value: + - id: ci1 + source: https://api.example.com/capability/capability-subscriptions/info + specversion: '1.0' + datacontenttype: application/json + type: org.camaraproject.capability.v0.capability-info-changed + time: '2025-05-06T00:00:00.000Z' + data: + capabilityInfo: + details: + - name: cap-qod-adi + version: 1.0.2 + createdAt: '2025-05-09T14:25:38Z' + overlayExtends: + - https://github.com/camaraproject/QualityOnDemand/blob/r2.2/code/API_definitions/quality-on-demand.yaml + - https://github.com/camaraproject/QualityOnDemand/blob/r2.2/code/API_definitions/qos-profiles.yaml + resourceScopes: + - phoneNumber: '+123456788' + mappingVersion: 1.0.0 + camaraCapabilitiesBitmap: 1 + bitmapCapabilities: + '0': + name: rr-qod-adi + version: 1.0.1 + restrictions: + - name: org.camaraproject.capability.v0.object-instance-restriction.accepted-device-identifiers + version: 1.0.1 + extends: https://github.com/camaraproject/QualityOnDemand/blob/r2.2/code/API_definitions/quality-on-demand.yaml + actions: + - target: $.components.schemas['Device'].properties['ipv4Address'] + remove: true + - target: $.components.schemas['Device'].properties['networkAccessIdentifier'] + remove: true diff --git a/code/API_definitions/notification-as-cloud-event.yaml b/code/API_definitions/notification-as-cloud-event.yaml index 0d92dff..32f8774 100644 --- a/code/API_definitions/notification-as-cloud-event.yaml +++ b/code/API_definitions/notification-as-cloud-event.yaml @@ -1,3 +1,4 @@ +--- openapi: 3.0.3 info: title: Event Notification using CloudEvents specifications @@ -5,50 +6,41 @@ info: The event notification endpoint is used by the API server to notify the API consumer that an event occurred. The notification is the message posted on listener side. # Introduction - A lot of CAMARA APIs offer the capability to API consumer to receive events. Event data are defined in each API definition but in order to provide consistency across CAMARA APIs and to increase interoperability we will use [cloudevents](https://cloudevents.io/) specifications. In particular, every CAMARA Event will be defined using [cloudevents-json-format](https://github.com/cloudevents/spec/blob/main/cloudevents/formats/json-format.md) # Relevant terms and definitions - * **Occurrence** : An "occurrence" is the capture of a statement of fact during the operation of a software system. - * **Event**: An "event" is a data record expressing an occurrence and its context. Events are routed from an event producer (the source) to interested event consumers. - * **Producer**: The "producer" is a specific instance, process or device that creates the data structure describing the CloudEvent. - * **Source**: The "source" is the context in which the occurrence happened. In a distributed system it might consist of multiple producers. If a source is not aware of CloudEvents, an external producer creates the CloudEvent on behalf of the source. - * **Consumer**: A "consumer" receives the event and acts upon it. It uses the context and data to execute some logic, which might lead to the occurrence of new events. - * **Data**: Domain-specific information about the occurrence (i.e. the payload). This might include information about the occurrence, details about the data that was changed, or more. # API Functionality - Only one endpoint/operation is provided: `POST /camara/cloudevents/webhook/v0` This endpoint describes the event notification received on subscription listener side when the event occurred. A detailed description of the event notification is provided in the [CAMARA API Event Subscription and Notification Guide](https://github.com/camaraproject/Commonalities/blob/main/documentation/CAMARA-API-Event-Subscription-and-Notification-Guide.md#3-event-notification) - termsOfService: http://swagger.io/terms/ contact: email: project-email@sample.com license: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0.html - version: wip + version: 0.4.0 externalDocs: description: Product documentation at CAMARA url: https://github.com/camaraproject/Commonalities security: - - notificationsBearerAuth: [] + - notificationsBearerAuth: [] servers: - url: '{apiRoot}' variables: @@ -62,9 +54,9 @@ tags: paths: /camara/cloudevents/webhook/v0: post: - tags: - - CAMARA Cloud Events - summary: "Cloud Event notification endpoint to notify consumer that statement of fact had occurred" + tags: [CAMARA Cloud Events] + summary: Cloud Event notification endpoint to notify consumer that statement + of fact had occurred description: | INFORMATIVE ENDPOINT: The value of this endpoint is freely declared by each client app by means of resource-based subscription or instance-based subscription. /camara/cloudevents/webhook/v0 is @@ -73,7 +65,7 @@ paths: URL, i.e.: notifications won't be sent to /event-notification/vX/your_webhook_notification_url. operationId: sendCamaraCloudEvents parameters: - - $ref: "#/components/parameters/x-correlator" + - $ref: '#/components/parameters/x-correlator' requestBody: required: true content: @@ -81,54 +73,44 @@ paths: schema: type: array items: - $ref: "#/components/schemas/CloudEvent" - + $ref: '#/components/schemas/CloudEvent' responses: - 204: + '204': description: No Content headers: x-correlator: - $ref: "#/components/headers/x-correlator" - 400: - $ref: "#/components/responses/Generic400" - 401: - $ref: "#/components/responses/Generic401" - 403: - $ref: "#/components/responses/Generic403" - 410: - $ref: "#/components/responses/Generic410" - 429: - $ref: "#/components/responses/Generic429" + $ref: '#/components/headers/x-correlator' + '400': + $ref: '#/components/responses/Generic400' + '401': + $ref: '#/components/responses/Generic401' + '403': + $ref: '#/components/responses/Generic403' + '410': + $ref: '#/components/responses/Generic410' + '429': + $ref: '#/components/responses/Generic429' components: securitySchemes: notificationsBearerAuth: - type: http - scheme: bearer - bearerFormat: "{$request.body#/sinkCredential.credentialType}" + $ref: CAMARA_common.yaml#/components/securitySchemes/notificationsBearerAuth schemas: CloudEvent: - $ref: 'CAMARA-subscriptions-openapi.yaml#/components/schemas/CamaraExtendedCloudEventsAttribute' - + $ref: CAMARA-subscriptions-openapi.yaml#/components/schemas/CamaraExtendedCloudEventsAttribute headers: x-correlator: - $ref: "CAMARA_common.yaml#/components/headers/x-correlator" - + $ref: CAMARA_common.yaml#/components/headers/x-correlator parameters: x-correlator: - $ref: "CAMARA_common.yaml#/components/parameters/x-correlator" - + $ref: CAMARA_common.yaml#/components/parameters/x-correlator responses: Generic400: - $ref: "CAMARA_common.yaml#/components/responses/Generic400" - + $ref: CAMARA_common.yaml#/components/responses/Generic400 Generic401: - $ref: "CAMARA_common.yaml#/components/responses/Generic401" - + $ref: CAMARA_common.yaml#/components/responses/Generic401 Generic403: - $ref: "CAMARA_common.yaml#/components/responses/Generic403" - + $ref: CAMARA_common.yaml#/components/responses/Generic403 Generic410: - $ref: "CAMARA_common.yaml#/components/responses/Generic410" - + $ref: CAMARA_common.yaml#/components/responses/Generic410 Generic429: - $ref: "CAMARA_common.yaml#/components/responses/Generic429" + $ref: CAMARA_common.yaml#/components/responses/Generic429 diff --git a/code/API_definitions/overlay-openapi.yaml b/code/API_definitions/overlay-openapi.yaml index f77a695..ca75261 100644 --- a/code/API_definitions/overlay-openapi.yaml +++ b/code/API_definitions/overlay-openapi.yaml @@ -1,3 +1,4 @@ +--- openapi: 3.0.3 info: title: Overlay @@ -9,45 +10,40 @@ info: license: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0.html - version: wip + version: 1.0.1 externalDocs: description: OpenAPI Overlay Specification url: https://spec.openapis.org/overlay/v1.0.0.html paths: {} - components: schemas: Overlay: description: | Common attributes of openAPI overlay [specification]("https://spec.openapis.org/overlay/latest.html"). - The list of actions MUST be applied in sequential order to ensure a consistent outcome. Actions are applied to the result of the previous action. This enables objects to be deleted in one action and then re-created in a subsequent action, for example. - The extends property can be used to indicate that the Overlay was designed to update a specific document. Where no extends is provided this implementation assumes an instance of the Components object '#/components/schemas/Components' is the 'document' root. type: object properties: info: - $ref: "#/components/schemas/Info-Object" + $ref: '#/components/schemas/Info-Object' extends: allOf: - - $ref: "#/components/schemas/Extends" + - $ref: '#/components/schemas/Extends' description: | URI of the document to overlay. Defaults to the root Components object if omitted. actions: - $ref: "#/components/schemas/Actions" + $ref: '#/components/schemas/Actions' required: [actions] - Extends: description: | URI reference that identifies the target document this overlay applies to. type: string format: uri minLength: 1 - Info-Object: description: Information Object type: object @@ -59,18 +55,16 @@ components: type: string minLength: 1 required: [title, version] - Actions: - description: A non-empty, ordered list of actions to be applied to the target document. + description: A non-empty, ordered list of actions to be applied to the target + document. type: array minItems: 1 uniqueItems: true items: - $ref: "#/components/schemas/Action-Object" - + $ref: '#/components/schemas/Action-Object' Action-Object: type: object - additionalProperties: false description: | Describes a change to be applied to every node selected by **target**. Exactly one of **update** or **remove** MUST be present (XOR). @@ -81,7 +75,6 @@ components: description: | **JSONPath** (RFC 9535 §4) selector that yields zero or more **non-null** nodes or "results". The results MAY resolve to an object or array. - **JSONPath** (RFC 9535 §4) examples: `$.paths['/foo'].get`   `$..security[*]` update: @@ -89,15 +82,15 @@ components: description: | A non-null replacement fragment to apply to the selected node(s). example: - foo: "bar" + foo: bar remove: type: boolean description: | When **true**, the selected node(s) are deleted default: false example: true - oneOf: # — enforce update xor remove — + oneOf: # — enforce update xor remove — - required: [update] - not: { required: [remove] } + not: {required: [remove]} - required: [remove] - not: { required: [update] } + not: {required: [update]} diff --git a/code/API_definitions/subscriptions-openapi.yaml b/code/API_definitions/subscriptions-openapi.yaml index e812271..86584d5 100644 --- a/code/API_definitions/subscriptions-openapi.yaml +++ b/code/API_definitions/subscriptions-openapi.yaml @@ -1,11 +1,11 @@ +--- openapi: 3.0.3 info: title: CloudEvents Subscriptions API - version: wip + version: 0.2-WIP license: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0.html - servers: - url: '{apiRoot}' variables: @@ -14,7 +14,6 @@ servers: description: Can be any notification server address sent by the client application security: - {} - paths: /subscriptions: get: @@ -22,7 +21,7 @@ paths: summary: getSubscriptions description: Retrieve multiple subscriptions responses: - "200": + '200': description: OK content: application/json: @@ -30,8 +29,8 @@ paths: type: array description: a list of subscriptions items: - $ref: "#/components/schemas/Subscription" - "400": + $ref: '#/components/schemas/Subscription' + '400': description: Bad request post: operationId: createSubscription @@ -42,34 +41,34 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/SubscriptionRequest" + $ref: '#/components/schemas/SubscriptionRequest' responses: - "201": + '201': description: Created successfully content: application/json: schema: - $ref: "#/components/schemas/Subscription" + $ref: '#/components/schemas/Subscription' headers: Location: schema: type: string format: url - "400": + '400': description: Invalid or malformed request options: operationId: getFeatures summary: getFeatures description: Discover supported features and methods for this endpoint responses: - "200": + '200': description: OK headers: Allow: schema: type: string - default: "GET,POST,OPTIONS" - "400": + default: GET,POST,OPTIONS + '400': description: Bad request /subscriptions/{id}: get: @@ -77,275 +76,280 @@ paths: summary: getSubscription description: Retrieve a subscription parameters: - - in: "path" - name: "id" + - in: path + name: id description: identifier of a specific subscription required: true schema: type: string responses: - "200": + '200': description: OK content: application/json: schema: - $ref: "#/components/schemas/Subscription" - "404": + $ref: '#/components/schemas/Subscription' + '404': description: Subscription not found put: operationId: updateSubscription summary: updateSubscription description: Update a subscription parameters: - - in: "path" - name: "id" + - in: path + name: id required: true schema: type: string description: The id of an existing subscription - requestBody: required: true content: application/json: schema: - $ref: "#/components/schemas/Subscription" + $ref: '#/components/schemas/Subscription' responses: - "200": + '200': description: OK content: application/json: schema: - $ref: "#/components/schemas/Subscription" - "400": + $ref: '#/components/schemas/Subscription' + '400': description: Invalid or malformed request - "404": + '404': description: Subscription not found delete: operationId: deleteSubscription summary: deleteSubscription description: Delete a subscription parameters: - - in: "path" - name: "id" + - in: path + name: id required: true schema: type: string description: The id of an existing subscription responses: - "200": + '200': description: Successfully deleted - "404": + '404': description: Subscription not found options: operationId: getSubscriptionFeatures summary: getSubscriptionFeatures description: Discover supported features and methods for this endpoint parameters: - - in: "path" - name: "id" + - in: path + name: id description: identifier of a specific subscription required: true schema: type: string responses: - "200": + '200': description: OK headers: Allow: schema: type: string - default: "GET,PUT,DELETE,OPTIONS" - "400": + default: GET,PUT,DELETE,OPTIONS + '400': description: Bad request components: schemas: SubscriptionRequest: properties: protocol: - $ref: "#/components/schemas/Protocol" + $ref: '#/components/schemas/Protocol' protocolsettings: oneOf: - - $ref: "#/components/schemas/ProtocolSettings" - - $ref: "#/components/schemas/AMQPSettings" - - $ref: "#/components/schemas/ApacheKafkaSettings" - - $ref: "#/components/schemas/HTTPSettings" - - $ref: "#/components/schemas/MQTTSettings" - - $ref: "#/components/schemas/NATSSettings" + - $ref: '#/components/schemas/ProtocolSettings' + - $ref: '#/components/schemas/AMQPSettings' + - $ref: '#/components/schemas/ApacheKafkaSettings' + - $ref: '#/components/schemas/HTTPSettings' + - $ref: '#/components/schemas/MQTTSettings' + - $ref: '#/components/schemas/NATSSettings' sink: type: string format: url - description: REQUIRED. The address to which events shall be delivered using the selected protocol. - example: "https://endpoint.example.com/webhook" + description: REQUIRED. The address to which events shall be delivered using + the selected protocol. + example: https://endpoint.example.com/webhook sinkcredential: oneOf: - - $ref: "#/components/schemas/SinkCredential" - - $ref: "#/components/schemas/AccessTokenCredential" - - $ref: "#/components/schemas/PlainCredential" - - $ref: "#/components/schemas/RefreshTokenCredential" + - $ref: '#/components/schemas/SinkCredential' + - $ref: '#/components/schemas/AccessTokenCredential' + - $ref: '#/components/schemas/PlainCredential' + - $ref: '#/components/schemas/RefreshTokenCredential' source: type: string format: uri-reference - description: OPTIONAL. Source to which the subscription applies. May be implied by the request address. + description: OPTIONAL. Source to which the subscription applies. May be + implied by the request address. types: - description: "CloudEvent types eligible to be delivered by this subscription" + description: CloudEvent types eligible to be delivered by this subscription type: array items: type: string filters: - description: "This filter evaluates to 'true' if all contained filters are 'true'" + description: This filter evaluates to 'true' if all contained filters are + 'true' type: array items: - title: "Filter entry" + title: Filter entry oneOf: - - $ref: "#/components/schemas/Filter" - - $ref: "#/components/schemas/AllFilter" - - $ref: "#/components/schemas/AnyFilter" - - $ref: "#/components/schemas/NotFilter" - - $ref: "#/components/schemas/ExactFilter" - - $ref: "#/components/schemas/PrefixFilter" - - $ref: "#/components/schemas/SuffixFilter" - - $ref: "#/components/schemas/SqlFilter" + - $ref: '#/components/schemas/Filter' + - $ref: '#/components/schemas/AllFilter' + - $ref: '#/components/schemas/AnyFilter' + - $ref: '#/components/schemas/NotFilter' + - $ref: '#/components/schemas/ExactFilter' + - $ref: '#/components/schemas/PrefixFilter' + - $ref: '#/components/schemas/SuffixFilter' + - $ref: '#/components/schemas/SqlFilter' config: - description: OPTIONAL. Implementation-specific configuration parameters needed by the subscription manager for acquiring events. + description: OPTIONAL. Implementation-specific configuration parameters + needed by the subscription manager for acquiring events. type: object additionalProperties: type: string - required: - - sink - - protocol + required: [sink, protocol] Subscription: type: object - title: "Subscription" + title: Subscription allOf: - - $ref: "#/components/schemas/SubscriptionRequest" + - $ref: '#/components/schemas/SubscriptionRequest' - type: object properties: id: type: string - description: REQUIRED. The unique identifier of the subscription in the scope of the subscription manager. - example: 1119920371 - required: - - id - - sink - - protocol + description: REQUIRED. The unique identifier of the subscription in + the scope of the subscription manager. + example: '1119920371' + required: [id, sink, protocol] Protocol: type: string - enum: ["HTTP", "MQTT3", "MQTT5", "AMQP", "NATS", "KAFKA"] + enum: [HTTP, MQTT3, MQTT5, AMQP, NATS, KAFKA] description: REQUIRED. Identifier of a delivery protocol. - example: "HTTP" + example: HTTP Filter: - title: "Filter" - description: "A filter from a selection of multiple filter types and dialects" + title: Filter + description: A filter from a selection of multiple filter types and dialects type: object additionalProperties: true AllFilter: allOf: - - $ref: "#/components/schemas/Filter" + - $ref: '#/components/schemas/Filter' - type: object - description: "all filter" + description: all filter properties: all: - description: "This filter evaluates to 'true' if all contained filters are 'true'" + description: This filter evaluates to 'true' if all contained filters + are 'true' type: array minItems: 1 items: - title: "Filter entry" + title: Filter entry oneOf: - - $ref: "#/components/schemas/Filter" - - $ref: "#/components/schemas/AllFilter" - - $ref: "#/components/schemas/AnyFilter" - - $ref: "#/components/schemas/NotFilter" - - $ref: "#/components/schemas/ExactFilter" - - $ref: "#/components/schemas/PrefixFilter" - - $ref: "#/components/schemas/SuffixFilter" - - $ref: "#/components/schemas/SqlFilter" + - $ref: '#/components/schemas/Filter' + - $ref: '#/components/schemas/AllFilter' + - $ref: '#/components/schemas/AnyFilter' + - $ref: '#/components/schemas/NotFilter' + - $ref: '#/components/schemas/ExactFilter' + - $ref: '#/components/schemas/PrefixFilter' + - $ref: '#/components/schemas/SuffixFilter' + - $ref: '#/components/schemas/SqlFilter' additionalProperties: false AnyFilter: allOf: - - $ref: "#/components/schemas/Filter" + - $ref: '#/components/schemas/Filter' - type: object - description: "any filter" + description: any filter properties: any: - description: "This filter evaluates to 'true' if any contained filters are 'true'" + description: This filter evaluates to 'true' if any contained filters + are 'true' type: array minItems: 1 items: - title: "Filter entry" + title: Filter entry oneOf: - - $ref: "#/components/schemas/Filter" - - $ref: "#/components/schemas/AllFilter" - - $ref: "#/components/schemas/AnyFilter" - - $ref: "#/components/schemas/NotFilter" - - $ref: "#/components/schemas/ExactFilter" - - $ref: "#/components/schemas/PrefixFilter" - - $ref: "#/components/schemas/SuffixFilter" - - $ref: "#/components/schemas/SqlFilter" + - $ref: '#/components/schemas/Filter' + - $ref: '#/components/schemas/AllFilter' + - $ref: '#/components/schemas/AnyFilter' + - $ref: '#/components/schemas/NotFilter' + - $ref: '#/components/schemas/ExactFilter' + - $ref: '#/components/schemas/PrefixFilter' + - $ref: '#/components/schemas/SuffixFilter' + - $ref: '#/components/schemas/SqlFilter' additionalProperties: false NotFilter: allOf: - - $ref: "#/components/schemas/Filter" + - $ref: '#/components/schemas/Filter' - type: object - description: "not filter" + description: not filter properties: not: type: object oneOf: - - $ref: "#/components/schemas/Filter" - - $ref: "#/components/schemas/AllFilter" - - $ref: "#/components/schemas/AnyFilter" - - $ref: "#/components/schemas/NotFilter" - - $ref: "#/components/schemas/ExactFilter" - - $ref: "#/components/schemas/PrefixFilter" - - $ref: "#/components/schemas/SuffixFilter" - - $ref: "#/components/schemas/SqlFilter" + - $ref: '#/components/schemas/Filter' + - $ref: '#/components/schemas/AllFilter' + - $ref: '#/components/schemas/AnyFilter' + - $ref: '#/components/schemas/NotFilter' + - $ref: '#/components/schemas/ExactFilter' + - $ref: '#/components/schemas/PrefixFilter' + - $ref: '#/components/schemas/SuffixFilter' + - $ref: '#/components/schemas/SqlFilter' additionalProperties: false ExactFilter: allOf: - - $ref: "#/components/schemas/Filter" + - $ref: '#/components/schemas/Filter' - type: object - title: "exact filter" - description: "This filter evaluates to 'true' if the 'value' exactly matches the value of the indicated CloudEvents context attribute" + title: exact filter + description: This filter evaluates to 'true' if the 'value' exactly matches + the value of the indicated CloudEvents context attribute properties: exact: - $ref: "#/components/schemas/CloudEventsAttribute" + $ref: '#/components/schemas/CloudEventsAttribute' additionalProperties: false PrefixFilter: allOf: - - $ref: "#/components/schemas/Filter" + - $ref: '#/components/schemas/Filter' - type: object - title: "prefix filter" - description: "This filter evaluates to 'true' if the 'value' is a prefix of the value of the indicated CloudEvents context attribute" + title: prefix filter + description: This filter evaluates to 'true' if the 'value' is a prefix + of the value of the indicated CloudEvents context attribute properties: prefix: - $ref: "#/components/schemas/CloudEventsAttribute" + $ref: '#/components/schemas/CloudEventsAttribute' additionalProperties: false SuffixFilter: allOf: - - $ref: "#/components/schemas/Filter" + - $ref: '#/components/schemas/Filter' - type: object - title: "suffix filter" - description: "This filter evaluates to 'true' if the 'value' is a suffix of the value of the indicated CloudEvents context attribute" + title: suffix filter + description: This filter evaluates to 'true' if the 'value' is a suffix + of the value of the indicated CloudEvents context attribute properties: suffix: - $ref: "#/components/schemas/CloudEventsAttribute" + $ref: '#/components/schemas/CloudEventsAttribute' additionalProperties: false SqlFilter: allOf: - - $ref: "#/components/schemas/Filter" + - $ref: '#/components/schemas/Filter' - type: object - description: "CESQL filter" + description: CESQL filter properties: sql: type: string - description: "The CESQL expression" + description: The CESQL expression additionalProperties: true CloudEventsAttribute: type: object - description: "CloudEvents defined attributes." - additionalProperties: # extension attributes - type: string + description: CloudEvents defined attributes. + additionalProperties: # extension attributes + # type: string + type: object properties: id: type: string @@ -355,7 +359,8 @@ components: description: Identifies the context in which an event happened. specversion: type: string - description: The version of the CloudEvents specification which the event uses. + description: The version of the CloudEvents specification which the event + uses. type: type: string description: Describes the type of event related to the originating occurrence. @@ -367,7 +372,8 @@ components: description: Identifies the schema that data adheres to. subject: type: string - description: Describes the subject of the event in the context of the event producer. + description: Describes the subject of the event in the context of the event + producer. time: type: string description: Timestamp of when the occurrence happened. @@ -377,7 +383,7 @@ components: HTTPSettings: type: object allOf: - - $ref: "#/components/schemas/ProtocolSettings" + - $ref: '#/components/schemas/ProtocolSettings' - properties: headers: type: object @@ -388,7 +394,7 @@ components: MQTTSettings: type: object allOf: - - $ref: "#/components/schemas/ProtocolSettings" + - $ref: '#/components/schemas/ProtocolSettings' - properties: topicname: type: string @@ -402,12 +408,11 @@ components: format: int32 userproperties: type: object - required: - - topicname + required: [topicname] AMQPSettings: type: object allOf: - - $ref: "#/components/schemas/ProtocolSettings" + - $ref: '#/components/schemas/ProtocolSettings' - properties: address: type: string @@ -415,15 +420,15 @@ components: type: string sendersettlementmode: type: string - enum: ["settled", "unsettled"] + enum: [settled, unsettled] linkProperties: type: object additionalProperties: - type: string + type: string ApacheKafkaSettings: type: object allOf: - - $ref: "#/components/schemas/ProtocolSettings" + - $ref: '#/components/schemas/ProtocolSettings' - properties: topicname: type: string @@ -433,30 +438,28 @@ components: type: string ackmode: type: integer - required: - - topicname + required: [topicname] NATSSettings: type: object allOf: - - $ref: "#/components/schemas/ProtocolSettings" + - $ref: '#/components/schemas/ProtocolSettings' - properties: subject: type: string - required: - - subject + required: [subject] SinkCredential: type: object properties: - credentialtype: - type: string - enum: ["PLAIN", "ACCESSTOKEN", "REFRESHTOKEN"] - description: "The type of the credential." + credentialtype: + type: string + enum: [PLAIN, ACCESSTOKEN, REFRESHTOKEN] + description: The type of the credential. additionalProperties: false PlainCredential: type: object description: A plain credential as a combination of an identifier and a secret. allOf: - - $ref: "#/components/schemas/SinkCredential" + - $ref: '#/components/schemas/SinkCredential' - properties: identifier: description: The identifier might be an account or username. @@ -468,36 +471,36 @@ components: type: object description: An access token credential. allOf: - - $ref: "#/components/schemas/SinkCredential" + - $ref: '#/components/schemas/SinkCredential' - properties: accesstoken: - description: REQUIRED. An access token is a previously acquired token granting access to the target resource. + description: REQUIRED. An access token is a previously acquired token + granting access to the target resource. type: string accesstokenexpiresutc: type: string format: date-time - description: RECOMMENDED. An absolute UTC instant at which the token shall be considered expired. + description: RECOMMENDED. An absolute UTC instant at which the token + shall be considered expired. accesstokentype: description: OPTIONAL. )Type of the access token (See https://tools.ietf.org/html/rfc6749#section-7.1). type: string default: bearer - required: - - accesstoken - - accesstokenexpiresutc + required: [accesstoken, accesstokenexpiresutc] RefreshTokenCredential: type: object description: An access token credential with a refresh token. allOf: - - $ref: "#/components/schemas/AccessTokenCredential" + - $ref: '#/components/schemas/AccessTokenCredential' - type: object properties: refreshtoken: - description: REQUIRED. An refresh token credential used to acquire access tokens. + description: REQUIRED. An refresh token credential used to acquire access + tokens. type: string refreshtokenendpoint: type: string format: uri - description: REQUIRED. A URL at which the refresh token can be traded for an access token. - required: - - refreshtoken - - refreshtokenendpoint + description: REQUIRED. A URL at which the refresh token can be traded + for an access token. + required: [refreshtoken, refreshtokenendpoint]