diff --git a/code/API_definitions/network-slice-assignment.yaml b/code/API_definitions/network-slice-assignment.yaml index 75890c2..7556fc0 100644 --- a/code/API_definitions/network-slice-assignment.yaml +++ b/code/API_definitions/network-slice-assignment.yaml @@ -49,7 +49,7 @@ info: As a specific rule, error `501 - NOT_IMPLEMENTED` can be only a possible error response if it is explicitly documented in the API. version: wip - x-camara-commonalities: "0.7" + x-camara-commonalities: 0.7.0 license: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0.html @@ -114,7 +114,7 @@ paths: content: application/cloudevents+json: schema: - $ref: "#/components/schemas/CloudEvent" + $ref: "#/components/schemas/ApiNotificationEvent" examples: ASSIGNMENT_COMPLETED_EVENT: $ref: "#/components/examples/ASSIGNMENT_COMPLETED_EVENT" @@ -362,11 +362,13 @@ components: description: Value for the x-correlator type: string pattern: ^[a-zA-Z0-9-_:;.\/<>{}]{0,256}$ + maxLength: 256 example: "b4333c46-49c0-4f62-80d7-f0ef930f1c46" SliceId: description: Slice ID in UUID format type: string format: uuid + maxLength: 36 DeviceInput: description: | Request to add device to a slice @@ -379,6 +381,7 @@ components: sink: type: string format: uri + maxLength: 2048 description: The URL where the API response will be asynchronously delivered, using the HTTP protocol. example: "https://endpoint.example.com/sink" sinkCredential: @@ -419,11 +422,13 @@ components: 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}$' + maxLength: 16 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. type: string + maxLength: 2048 example: "123456789@example.com" DeviceIpv4Address: @@ -453,6 +458,7 @@ components: description: A single IPv4 address with no subnet mask type: string format: ipv4 + maxLength: 15 example: "84.125.93.10" Port: @@ -466,6 +472,7 @@ components: 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 + maxLength: 45 example: 2001:db8:85a3:8d3:1319:8a2e:370:7344 ReleaseDeviceInput: @@ -621,6 +628,7 @@ components: sink: type: string format: uri + maxLength: 2048 description: The URL where the API response will be asynchronously delivered, using the HTTP protocol. example: "https://endpoint.example.com/sink" sinkCredential: @@ -730,17 +738,13 @@ components: maximum: 20 TimePeriod: + type: object + description: A period of time defined by a start date and an optional end date. If `endDate` is not included, then the period has no ending date. 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. - example: "2024-06-01T12:00:00Z" + $ref: "#/components/schemas/DateTime" 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. - example: "2024-06-02T12:00:00Z" + $ref: "#/components/schemas/DateTime" required: - startDate @@ -833,25 +837,35 @@ components: maximum: 180 ErrorInfo: - description: Common schema for errors type: object + description: A structured error response providing details about a failed request, including the HTTP status code, an error code, and a human-readable message + required: + - status + - code + - message properties: status: type: integer - description: HTTP status code returned along with this error response + format: int32 + minimum: 100 + maximum: 599 + description: HTTP response status code code: type: string - description: Code given to this error + maxLength: 96 + description: A human-readable code to describe the error message: type: string - description: Detailed error description - required: - - status - - code - - message + maxLength: 512 + description: A human-readable description of what the event represents CloudEvent: - description: The notification callback + type: object + description: | + CloudEvents 1.0 specification envelope. + This schema is the stable base for all CAMARA event notifications. + It imposes no constraints on `type` values or `data` structure — + those concerns belong to the API-specific and lifecycle group schemas. required: - id - source @@ -861,16 +875,17 @@ components: properties: id: type: string - description: identifier of this event, that must be unique in the source context. - minLength: 1 + maxLength: 256 + description: Identifier of this event, unique within the source context. source: - $ref: '#/components/schemas/Source' + $ref: "#/components/schemas/Source" type: type: string - description: The type of the event - enum: - - "org.camaraproject.network-slice-assignment.v0.status-changed" - minLength: 25 + maxLength: 512 + description: | + Identifies the event type. CAMARA APIs use reverse-DNS notation: + `org.camaraproject...` + The api-name segment makes each type globally unique across API groups. specversion: type: string description: Version of the specification to which this event conforms (must be 1.0 if it conforms to cloudevents 1.0.2 version) @@ -883,21 +898,44 @@ components: - application/json data: type: object - description: Event details payload described in each CAMARA API and referenced by its type + description: Event details payload. Structure is defined by each concrete event schema. time: $ref: "#/components/schemas/DateTime" + + ApiEventType: + type: string + description: | + Enum of API-specific event type strings for this API project. + The reverse-DNS prefix `org.camaraproject.` makes each value + globally unique, so two different API groups can independently define + identically-named event types without any collision risk. + enum: + - org.camaraproject.network-slice-assignment.v0.status-changed + ApiNotificationEvent: + description: | + API-specific notification event group. + Extends the CloudEvent envelope and constrains `type` to the set of + event types defined by this API project. + Adding a new event type only requires updating ApiEventType and the + discriminator mapping below — the CloudEvent base never changes. + allOf: + - $ref: "#/components/schemas/CloudEvent" + - type: object + properties: + type: + $ref: "#/components/schemas/ApiEventType" discriminator: - propertyName: type + propertyName: "type" mapping: org.camaraproject.network-slice-assignment.v0.status-changed: "#/components/schemas/AssignmentDeviceEvent" - AssignmentDeviceEvent: description: Event to notify about device assignment status change allOf: - - $ref: "#/components/schemas/CloudEvent" + - $ref: "#/components/schemas/ApiNotificationEvent" - type: object properties: data: + type: object description: Event details depending on the event type allOf: - $ref: "#/components/schemas/DeviceAssignmentInfo" @@ -907,6 +945,7 @@ components: DateTime: type: string format: date-time + maxLength: 64 description: | Timestamp of when the occurrence happened. It must follow [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) and must have time zone. WARN: This optional field in CloudEvents specification is required in CAMARA APIs implementation. @@ -916,6 +955,7 @@ components: type: string format: uri-reference minLength: 1 + maxLength: 2048 description: | Identifies the context in which an event happened - be a non-empty `URI-reference` like: - URI with a DNS authority: @@ -935,49 +975,32 @@ components: credentialType: type: string enum: - - PLAIN - ACCESSTOKEN - - REFRESHTOKEN + - PRIVATE_KEY_JWT description: | - The type of the credential. - Note: Type of the credential - MUST be set to ACCESSTOKEN for now + The type of the credential - MUST be set to ACCESSTOKEN or PRIVATE_KEY_JWT for now discriminator: propertyName: credentialType mapping: - PLAIN: "#/components/schemas/PlainCredential" ACCESSTOKEN: "#/components/schemas/AccessTokenCredential" - REFRESHTOKEN: "#/components/schemas/RefreshTokenCredential" + PRIVATE_KEY_JWT: "#/components/schemas/PrivateKeyJWTCredential" required: - credentialType - PlainCredential: - type: object - description: A plain credential as a combination of an identifier and a secret. - allOf: - - $ref: "#/components/schemas/SinkCredential" - - type: object - required: - - identifier - - secret - properties: - identifier: - description: The identifier might be an account or username. - type: string - secret: - description: The secret might be a password or passphrase. - type: string AccessTokenCredential: type: object - description: An access token credential. + description: An access token credential. This type of credential is meant to be used by API Consumers that have limited capabilities to handle authorization requests. allOf: - $ref: "#/components/schemas/SinkCredential" - type: object 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 token granting access to the target resource. type: string + maxLength: 4096 accessTokenExpiresUtc: type: string format: date-time + maxLength: 64 description: | REQUIRED. An absolute (UTC) timestamp at which the token shall be considered expired. In the case of an ACCESS_TOKEN_EXPIRED termination reason, implementation should notify the client before the expiration date. @@ -993,43 +1016,11 @@ components: - accessToken - accessTokenExpiresUtc - accessTokenType - RefreshTokenCredential: + PrivateKeyJWTCredential: type: object - description: An access token credential with a refresh token. + description: Use PRIVATE_KEY_JWT to get an access token. The authorization server information needed for this type of sink credential (token endpoint, client ID, JWKS URL) is shared upfront between the client and the CAMARA entity. This type of credential is to be used by clients that have an authorization server. allOf: - $ref: "#/components/schemas/SinkCredential" - - type: object - properties: - accessToken: - 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: | - REQUIRED. An absolute (UTC) timestamp at which the token shall be considered expired. - In the case of an ACCESS_TOKEN_EXPIRED termination reason, implementation should notify the client before the expiration date. - If the access token is a JWT and registered "exp" (Expiration Time) claim is present, the two expiry times should match. - It must follow [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) and must have time zone. - example: "2023-07-03T12:27:08.312Z" - accessTokenType: - description: REQUIRED. Type of the access token (See [OAuth 2.0](https://tools.ietf.org/html/rfc6749#section-7.1)). - type: string - enum: - - bearer - refreshToken: - 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: - - accessToken - - accessTokenExpiresUtc - - accessTokenType - - refreshToken - - refreshTokenEndpoint responses: Generic400: diff --git a/code/API_definitions/network-slice-booking.yaml b/code/API_definitions/network-slice-booking.yaml index 6919aa9..3b92e40 100644 --- a/code/API_definitions/network-slice-booking.yaml +++ b/code/API_definitions/network-slice-booking.yaml @@ -44,7 +44,7 @@ info: As a specific rule, error `501 - NOT_IMPLEMENTED` can be only a possible error response if it is explicitly documented in the API. version: wip - x-camara-commonalities: "0.7" + x-camara-commonalities: 0.7.0 license: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0.html @@ -105,7 +105,7 @@ paths: content: application/cloudevents+json: schema: - $ref: "#/components/schemas/CloudEvent" + $ref: "#/components/schemas/ApiNotificationEvent" examples: SLICE_CREATED_EVENT_CIRCLE: $ref: "#/components/examples/SLICE_CREATED_EVENT_CIRCLE" @@ -277,11 +277,13 @@ components: description: Value for the x-correlator type: string pattern: ^[a-zA-Z0-9-_:;.\/<>{}]{0,256}$ + maxLength: 256 example: "b4333c46-49c0-4f62-80d7-f0ef930f1c46" SliceId: description: Slice ID in UUID format type: string format: uuid + maxLength: 36 SliceInfo: description: Slice related information. allOf: @@ -318,6 +320,7 @@ components: sink: type: string format: uri + maxLength: 2048 description: The URL where the API response will be asynchronously delivered, using the HTTP protocol. example: "https://endpoint.example.com/sink" sinkCredential: @@ -427,17 +430,13 @@ components: maximum: 20 TimePeriod: + type: object + description: A period of time defined by a start date and an optional end date. If `endDate` is not included, then the period has no ending date. 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. - example: "2024-06-01T12:00:00Z" + $ref: "#/components/schemas/DateTime" 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. - example: "2024-06-02T12:00:00Z" + $ref: "#/components/schemas/DateTime" required: - startDate @@ -530,25 +529,35 @@ components: maximum: 180 ErrorInfo: - description: Common schema for errors type: object + description: A structured error response providing details about a failed request, including the HTTP status code, an error code, and a human-readable message + required: + - status + - code + - message properties: status: type: integer - description: HTTP status code returned along with this error response + format: int32 + minimum: 100 + maximum: 599 + description: HTTP response status code code: type: string - description: Code given to this error + maxLength: 96 + description: A human-readable code to describe the error message: type: string - description: Detailed error description - required: - - status - - code - - message + maxLength: 512 + description: A human-readable description of what the event represents CloudEvent: - description: The notification callback + type: object + description: | + CloudEvents 1.0 specification envelope. + This schema is the stable base for all CAMARA event notifications. + It imposes no constraints on `type` values or `data` structure — + those concerns belong to the API-specific and lifecycle group schemas. required: - id - source @@ -558,16 +567,17 @@ components: properties: id: type: string - description: identifier of this event, that must be unique in the source context. - minLength: 1 + maxLength: 256 + description: Identifier of this event, unique within the source context. source: - $ref: '#/components/schemas/Source' + $ref: "#/components/schemas/Source" type: type: string - description: The type of the event - enum: - - "org.camaraproject.network-slice-booking.v0.status-changed" - minLength: 25 + maxLength: 512 + description: | + Identifies the event type. CAMARA APIs use reverse-DNS notation: + `org.camaraproject...` + The api-name segment makes each type globally unique across API groups. specversion: type: string description: Version of the specification to which this event conforms (must be 1.0 if it conforms to cloudevents 1.0.2 version) @@ -580,21 +590,47 @@ components: - application/json data: type: object - description: Event details payload described in each CAMARA API and referenced by its type + description: Event details payload. Structure is defined by each concrete event schema. time: $ref: "#/components/schemas/DateTime" discriminator: propertyName: type mapping: org.camaraproject.network-slice-booking.v0.status-changed: "#/components/schemas/SliceCreatedEvent" - - SliceCreatedEvent: - description: Event to notify a slice creation status change + ApiEventType: + type: string + description: | + Enum of API-specific event type strings for this API project. + The reverse-DNS prefix `org.camaraproject.` makes each value + globally unique, so two different API groups can independently define + identically-named event types without any collision risk. + enum: + - org.camaraproject.network-slice-booking.v0.status-changed + ApiNotificationEvent: + description: | + API-specific notification event group. + Extends the CloudEvent envelope and constrains `type` to the set of + event types defined by this API project. + Adding a new event type only requires updating ApiEventType and the + discriminator mapping below — the CloudEvent base never changes. allOf: - $ref: "#/components/schemas/CloudEvent" + - type: object + properties: + type: + $ref: "#/components/schemas/ApiEventType" + discriminator: + propertyName: "type" + mapping: + org.camaraproject.network-slice-booking.v0.status-changed: "#/components/schemas/SliceCreatedEvent" + SliceCreatedEvent: + description: Event to notify about device assignment status change + allOf: + - $ref: "#/components/schemas/ApiNotificationEvent" - type: object properties: data: + type: object description: Event details depending on the event type allOf: - $ref: "#/components/schemas/SliceInfo" @@ -604,6 +640,7 @@ components: DateTime: type: string format: date-time + maxLength: 64 description: | Timestamp of when the occurrence happened. It must follow [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) and must have time zone. WARN: This optional field in CloudEvents specification is required in CAMARA APIs implementation. @@ -613,6 +650,7 @@ components: type: string format: uri-reference minLength: 1 + maxLength: 2048 description: | Identifies the context in which an event happened - be a non-empty `URI-reference` like: - URI with a DNS authority: @@ -632,49 +670,32 @@ components: credentialType: type: string enum: - - PLAIN - ACCESSTOKEN - - REFRESHTOKEN + - PRIVATE_KEY_JWT description: | - The type of the credential. - Note: Type of the credential - MUST be set to ACCESSTOKEN for now + The type of the credential - MUST be set to ACCESSTOKEN or PRIVATE_KEY_JWT for now discriminator: propertyName: credentialType mapping: - PLAIN: "#/components/schemas/PlainCredential" ACCESSTOKEN: "#/components/schemas/AccessTokenCredential" - REFRESHTOKEN: "#/components/schemas/RefreshTokenCredential" + PRIVATE_KEY_JWT: "#/components/schemas/PrivateKeyJWTCredential" required: - credentialType - PlainCredential: - type: object - description: A plain credential as a combination of an identifier and a secret. - allOf: - - $ref: "#/components/schemas/SinkCredential" - - type: object - required: - - identifier - - secret - properties: - identifier: - description: The identifier might be an account or username. - type: string - secret: - description: The secret might be a password or passphrase. - type: string AccessTokenCredential: type: object - description: An access token credential. + description: An access token credential. This type of credential is meant to be used by API Consumers that have limited capabilities to handle authorization requests. allOf: - $ref: "#/components/schemas/SinkCredential" - type: object 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 token granting access to the target resource. type: string + maxLength: 4096 accessTokenExpiresUtc: type: string format: date-time + maxLength: 64 description: | REQUIRED. An absolute (UTC) timestamp at which the token shall be considered expired. In the case of an ACCESS_TOKEN_EXPIRED termination reason, implementation should notify the client before the expiration date. @@ -690,43 +711,11 @@ components: - accessToken - accessTokenExpiresUtc - accessTokenType - RefreshTokenCredential: + PrivateKeyJWTCredential: type: object - description: An access token credential with a refresh token. + description: Use PRIVATE_KEY_JWT to get an access token. The authorization server information needed for this type of sink credential (token endpoint, client ID, JWKS URL) is shared upfront between the client and the CAMARA entity. This type of credential is to be used by clients that have an authorization server. allOf: - $ref: "#/components/schemas/SinkCredential" - - type: object - properties: - accessToken: - 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: | - REQUIRED. An absolute (UTC) timestamp at which the token shall be considered expired. - In the case of an ACCESS_TOKEN_EXPIRED termination reason, implementation should notify the client before the expiration date. - If the access token is a JWT and registered "exp" (Expiration Time) claim is present, the two expiry times should match. - It must follow [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) and must have time zone. - example: "2023-07-03T12:27:08.312Z" - accessTokenType: - description: REQUIRED. Type of the access token (See [OAuth 2.0](https://tools.ietf.org/html/rfc6749#section-7.1)). - type: string - enum: - - bearer - refreshToken: - 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: - - accessToken - - accessTokenExpiresUtc - - accessTokenType - - refreshToken - - refreshTokenEndpoint responses: Generic400: @@ -953,6 +942,13 @@ components: upStreamDelayBudget: value: 12 unit: Milliseconds + sink: + "https://endpoint.example.com/sink" + sinkCredential: + credentialType: ACCESSTOKEN + accessToken: "" + accessTokenExpiresUtc: "2025-12-31T23:59:59Z" + accessTokenType: bearer RETRIEVAL_POLYGON: value: serviceTime: @@ -983,6 +979,13 @@ components: upStreamDelayBudget: value: 12 unit: Milliseconds + sink: + "https://endpoint.example.com/sink" + sinkCredential: + credentialType: ACCESSTOKEN + accessToken: "" + accessTokenExpiresUtc: "2025-12-31T23:59:59Z" + accessTokenType: bearer RESPONSE_CIRCLE: value: serviceTime: