feat: deliver versioned SIP config to Cells
This commit is contained in:
@@ -0,0 +1,225 @@
|
||||
# yaml-language-server: $schema=https://json-schema.org/draft/2020-12/schema
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: agent-call Cell Agent API
|
||||
version: 1.0.0
|
||||
description: >-
|
||||
Restricted mTLS API used by the SIP management backend to deliver a
|
||||
versioned Trunk snapshot to one voice Cell. The Cell validates the SHA-256
|
||||
snapshot, applies it with an atomic file replacement, reloads Asterisk,
|
||||
restores the previous file on reload failure, and returns applied only
|
||||
after the reload succeeds. A disabled snapshot removes the Cell-local
|
||||
Trunk fragment and reloads Asterisk.
|
||||
servers:
|
||||
- url: https://cell.internal:9443
|
||||
description: Cell management network only
|
||||
tags:
|
||||
- name: health
|
||||
- name: trunk-apply
|
||||
paths:
|
||||
/healthz/live:
|
||||
get:
|
||||
tags: [health]
|
||||
operationId: live
|
||||
responses:
|
||||
'200':
|
||||
description: Cell Agent is alive
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/Health'}
|
||||
/v1/sip/trunks/{trunk_id}/apply:
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/TrunkId'}
|
||||
post:
|
||||
tags: [trunk-apply]
|
||||
operationId: applyTrunk
|
||||
security: [{CellManagementMtls: []}]
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/RequestId'}
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/Publication'}
|
||||
responses:
|
||||
'200':
|
||||
description: Asterisk has loaded the exact snapshot
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/Acknowledgement'}
|
||||
'400': {$ref: '#/components/responses/BadRequest'}
|
||||
'403': {$ref: '#/components/responses/Forbidden'}
|
||||
'409':
|
||||
description: Revision is stale or has a gap
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/ErrorResponse'}
|
||||
'502':
|
||||
description: Asterisk rejected the apply or reload
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/ErrorResponse'}
|
||||
/v1/sip/trunks/{trunk_id}/state:
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/TrunkId'}
|
||||
get:
|
||||
tags: [trunk-apply]
|
||||
operationId: getTrunkState
|
||||
security: [{CellManagementMtls: []}]
|
||||
responses:
|
||||
'200':
|
||||
description: Durable Cell apply state
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/State'}
|
||||
'404': {$ref: '#/components/responses/NotFound'}
|
||||
components:
|
||||
securitySchemes:
|
||||
CellManagementMtls:
|
||||
type: mutualTLS
|
||||
description: Management backend client certificate signed by the Cell CA.
|
||||
parameters:
|
||||
TrunkId:
|
||||
name: trunk_id
|
||||
in: path
|
||||
required: true
|
||||
schema: {type: string, pattern: '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'}
|
||||
RequestId:
|
||||
name: X-Request-ID
|
||||
in: header
|
||||
required: true
|
||||
schema: {type: string, minLength: 1, maxLength: 128}
|
||||
schemas:
|
||||
Health:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [status, mode, cell_id]
|
||||
properties:
|
||||
status: {type: string, const: ok}
|
||||
mode: {type: string, const: real}
|
||||
cell_id: {type: string}
|
||||
CodecProfile:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [allowed, preferred]
|
||||
properties:
|
||||
allowed:
|
||||
type: array
|
||||
minItems: 1
|
||||
uniqueItems: true
|
||||
items: {type: string, enum: [PCMA, PCMU]}
|
||||
preferred: {type: string, enum: [PCMA, PCMU]}
|
||||
SipConfig:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [host, port, transport, auth_mode, register, credential_ref]
|
||||
properties:
|
||||
host: {type: string, minLength: 1, maxLength: 253}
|
||||
port: {type: integer, minimum: 1, maximum: 65535}
|
||||
transport: {type: string, enum: [udp, tcp, tls]}
|
||||
auth_mode: {type: string, enum: [ip, digest]}
|
||||
register: {type: boolean}
|
||||
credential_ref:
|
||||
type: [string, 'null']
|
||||
description: Secret-store reference only; plaintext is forbidden.
|
||||
TrunkConfig:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required:
|
||||
- display_name
|
||||
- enabled
|
||||
- sip
|
||||
- codec_profile
|
||||
- caller_ids
|
||||
- dial_prefix
|
||||
- egress_pool_id
|
||||
- max_concurrency
|
||||
- max_cps
|
||||
properties:
|
||||
display_name: {type: string, minLength: 1, maxLength: 256}
|
||||
enabled: {type: boolean}
|
||||
sip: {$ref: '#/components/schemas/SipConfig'}
|
||||
codec_profile: {$ref: '#/components/schemas/CodecProfile'}
|
||||
caller_ids:
|
||||
type: array
|
||||
minItems: 1
|
||||
uniqueItems: true
|
||||
items: {type: string, minLength: 1, maxLength: 128}
|
||||
dial_prefix: {type: string, maxLength: 32}
|
||||
egress_pool_id: {type: string}
|
||||
max_concurrency: {type: integer, minimum: 1}
|
||||
max_cps: {type: integer, minimum: 1}
|
||||
Publication:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [mode, cell_id, trunk_id, revision, config, config_sha256]
|
||||
properties:
|
||||
mode: {type: string, const: real}
|
||||
cell_id: {type: string}
|
||||
trunk_id: {type: string}
|
||||
revision: {type: integer, minimum: 1}
|
||||
config: {$ref: '#/components/schemas/TrunkConfig'}
|
||||
config_sha256:
|
||||
type: string
|
||||
pattern: '^[0-9a-f]{64}$'
|
||||
Acknowledgement:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required:
|
||||
[mode, cell_id, trunk_id, revision, config_sha256, status, idempotent]
|
||||
properties:
|
||||
mode: {type: string, const: real}
|
||||
cell_id: {type: string}
|
||||
trunk_id: {type: string}
|
||||
revision: {type: integer, minimum: 1}
|
||||
config_sha256: {type: string, pattern: '^[0-9a-f]{64}$'}
|
||||
status: {type: string, const: applied}
|
||||
idempotent: {type: boolean}
|
||||
State:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required:
|
||||
[
|
||||
mode,
|
||||
cell_id,
|
||||
trunk_id,
|
||||
desired_revision,
|
||||
applied_revision,
|
||||
status,
|
||||
updated_at,
|
||||
]
|
||||
properties:
|
||||
mode: {type: string, const: real}
|
||||
cell_id: {type: string}
|
||||
trunk_id: {type: string}
|
||||
desired_revision: {type: integer, minimum: 1}
|
||||
applied_revision: {type: integer, minimum: 0}
|
||||
status: {type: string, enum: [applying, applied, failed]}
|
||||
last_error: {type: [string, 'null']}
|
||||
updated_at: {type: string, format: date-time}
|
||||
ErrorResponse:
|
||||
type: object
|
||||
required: [error]
|
||||
properties:
|
||||
error:
|
||||
type: object
|
||||
required: [code, message]
|
||||
properties:
|
||||
code: {type: string}
|
||||
message: {type: string}
|
||||
responses:
|
||||
BadRequest:
|
||||
description: Invalid publication or hash
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/ErrorResponse'}
|
||||
Forbidden:
|
||||
description: Certificate or Cell identity is not authorized
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/ErrorResponse'}
|
||||
NotFound:
|
||||
description: State does not exist
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/ErrorResponse'}
|
||||
@@ -0,0 +1,564 @@
|
||||
# yaml-language-server: $schema=https://json-schema.org/draft/2020-12/schema
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: agent-call Asterisk/SIP Management API
|
||||
version: 1.0.0
|
||||
description: >-
|
||||
Independent Asterisk/SIP management backend. Admin write operations are
|
||||
separate from the SaaS read-only Trunk directory and from ordinary
|
||||
scheduling APIs. In mock mode publication records are intents only. In
|
||||
real mode a publication is successful only after every selected Cell Agent
|
||||
returns a matching mTLS acknowledgement.
|
||||
servers:
|
||||
- url: https://sip-admin.internal
|
||||
description: Restricted operator management network
|
||||
- url: https://sip-read.internal
|
||||
description: SaaS read-only service network
|
||||
tags:
|
||||
- name: health
|
||||
- name: admin-trunks
|
||||
- name: admin-cells
|
||||
- name: saas-readonly
|
||||
paths:
|
||||
/healthz/live:
|
||||
get:
|
||||
tags: [health]
|
||||
operationId: live
|
||||
responses:
|
||||
'200':
|
||||
description: Service is alive
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Health'
|
||||
/admin/v1/trunks:
|
||||
get:
|
||||
tags: [admin-trunks]
|
||||
operationId: listAdminTrunks
|
||||
security: [{SipAdminBearer: []}]
|
||||
responses:
|
||||
'200':
|
||||
description: All Trunks, including unpublished revisions
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/AdminTrunkList'
|
||||
'401': {$ref: '#/components/responses/Unauthorized'}
|
||||
'403': {$ref: '#/components/responses/Forbidden'}
|
||||
/admin/v1/trunks/{trunk_id}:
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/TrunkId'}
|
||||
get:
|
||||
tags: [admin-trunks]
|
||||
operationId: getAdminTrunk
|
||||
security: [{SipAdminBearer: []}]
|
||||
responses:
|
||||
'200':
|
||||
description: Trunk configuration and revisions
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/AdminTrunk'
|
||||
'401': {$ref: '#/components/responses/Unauthorized'}
|
||||
'404': {$ref: '#/components/responses/NotFound'}
|
||||
put:
|
||||
tags: [admin-trunks]
|
||||
operationId: createTrunkRevision
|
||||
security: [{SipAdminBearer: []}]
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/IfMatch'}
|
||||
- {$ref: '#/components/parameters/RequestId'}
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/TrunkConfig'
|
||||
responses:
|
||||
'200':
|
||||
description: New draft revision for an existing Trunk
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/AdminTrunk'}
|
||||
'201':
|
||||
description: New Trunk with its first draft revision
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/AdminTrunk'}
|
||||
'400': {$ref: '#/components/responses/BadRequest'}
|
||||
'401': {$ref: '#/components/responses/Unauthorized'}
|
||||
'409': {$ref: '#/components/responses/Conflict'}
|
||||
/admin/v1/trunks/{trunk_id}/publish:
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/TrunkId'}
|
||||
post:
|
||||
tags: [admin-trunks]
|
||||
operationId: publishTrunk
|
||||
security: [{SipAdminBearer: []}]
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/IfMatch'}
|
||||
- {$ref: '#/components/parameters/RequestId'}
|
||||
responses:
|
||||
'200':
|
||||
description: >-
|
||||
Published revision after all selected Cell acknowledgements
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/AdminTrunk'}
|
||||
'401': {$ref: '#/components/responses/Unauthorized'}
|
||||
'409': {$ref: '#/components/responses/Conflict'}
|
||||
/admin/v1/trunks/{trunk_id}/disable:
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/TrunkId'}
|
||||
post:
|
||||
tags: [admin-trunks]
|
||||
operationId: disableTrunk
|
||||
security: [{SipAdminBearer: []}]
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/IfMatch'}
|
||||
- {$ref: '#/components/parameters/RequestId'}
|
||||
responses:
|
||||
'200':
|
||||
description: Trunk disabled after selected Cell acknowledgements
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/AdminTrunk'}
|
||||
'401': {$ref: '#/components/responses/Unauthorized'}
|
||||
'409': {$ref: '#/components/responses/Conflict'}
|
||||
/admin/v1/trunks/{trunk_id}/rollback:
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/TrunkId'}
|
||||
post:
|
||||
tags: [admin-trunks]
|
||||
operationId: rollbackTrunk
|
||||
security: [{SipAdminBearer: []}]
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/IfMatch'}
|
||||
- {$ref: '#/components/parameters/RequestId'}
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [target_revision]
|
||||
properties:
|
||||
target_revision: {type: integer, minimum: 1}
|
||||
responses:
|
||||
'200':
|
||||
description: >-
|
||||
New revision copied from the target after Cell acknowledgements
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/AdminTrunk'}
|
||||
'401': {$ref: '#/components/responses/Unauthorized'}
|
||||
'409': {$ref: '#/components/responses/Conflict'}
|
||||
/admin/v1/trunks/{trunk_id}/publications:
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/TrunkId'}
|
||||
get:
|
||||
tags: [admin-trunks]
|
||||
operationId: listTrunkPublications
|
||||
security: [{SipAdminBearer: []}]
|
||||
responses:
|
||||
'200':
|
||||
description: Per-Cell publication intents
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [mode, publications]
|
||||
properties:
|
||||
mode: {$ref: '#/components/schemas/Mode'}
|
||||
publications:
|
||||
type: array
|
||||
items: {$ref: '#/components/schemas/Publication'}
|
||||
'401': {$ref: '#/components/responses/Unauthorized'}
|
||||
'404': {$ref: '#/components/responses/NotFound'}
|
||||
/admin/v1/trunks/{trunk_id}/audit:
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/TrunkId'}
|
||||
get:
|
||||
tags: [admin-trunks]
|
||||
operationId: listTrunkAudit
|
||||
security: [{SipAdminBearer: []}]
|
||||
responses:
|
||||
'200':
|
||||
description: Immutable management audit entries
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [mode, audit]
|
||||
properties:
|
||||
mode: {$ref: '#/components/schemas/Mode'}
|
||||
audit:
|
||||
type: array
|
||||
items: {$ref: '#/components/schemas/AuditEntry'}
|
||||
'401': {$ref: '#/components/responses/Unauthorized'}
|
||||
'404': {$ref: '#/components/responses/NotFound'}
|
||||
/admin/v1/cells:
|
||||
get:
|
||||
tags: [admin-cells]
|
||||
operationId: listCells
|
||||
security: [{SipAdminBearer: []}]
|
||||
responses:
|
||||
'200':
|
||||
description: Registered multi-machine voice Cells
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [mode, cells]
|
||||
properties:
|
||||
mode: {$ref: '#/components/schemas/Mode'}
|
||||
cells:
|
||||
type: array
|
||||
items: {$ref: '#/components/schemas/Cell'}
|
||||
'401': {$ref: '#/components/responses/Unauthorized'}
|
||||
/admin/v1/cells/{cell_id}:
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/CellId'}
|
||||
put:
|
||||
tags: [admin-cells]
|
||||
operationId: registerCell
|
||||
security: [{SipAdminBearer: []}]
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/IfMatch'}
|
||||
- {$ref: '#/components/parameters/RequestId'}
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/CellConfig'}
|
||||
responses:
|
||||
'200':
|
||||
description: Updated Cell revision
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/Cell'}
|
||||
'201':
|
||||
description: Registered Cell
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/Cell'}
|
||||
'401': {$ref: '#/components/responses/Unauthorized'}
|
||||
'409': {$ref: '#/components/responses/Conflict'}
|
||||
/readonly/v1/sip/trunks:
|
||||
get:
|
||||
tags: [saas-readonly]
|
||||
operationId: listAuthorizedTrunks
|
||||
security: [{SaasTrunkReadBearer: []}]
|
||||
responses:
|
||||
'200':
|
||||
description: Published Trunks authorized for this SaaS principal
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ReadonlyTrunkList'
|
||||
'401': {$ref: '#/components/responses/Unauthorized'}
|
||||
/readonly/v1/sip/trunks/{trunk_id}:
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/TrunkId'}
|
||||
get:
|
||||
tags: [saas-readonly]
|
||||
operationId: getAuthorizedTrunk
|
||||
security: [{SaasTrunkReadBearer: []}]
|
||||
responses:
|
||||
'200':
|
||||
description: Published, sanitized Trunk metadata
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/ReadonlyTrunk'}
|
||||
'401': {$ref: '#/components/responses/Unauthorized'}
|
||||
'404': {$ref: '#/components/responses/NotFound'}
|
||||
components:
|
||||
securitySchemes:
|
||||
SipAdminBearer:
|
||||
type: http
|
||||
scheme: bearer
|
||||
bearerFormat: opaque
|
||||
description: >-
|
||||
Dedicated operator/backend credential for SIP management writes. It is
|
||||
not accepted by the SaaS read-only API or ordinary scheduling API.
|
||||
SaasTrunkReadBearer:
|
||||
type: http
|
||||
scheme: bearer
|
||||
bearerFormat: opaque
|
||||
description: >-
|
||||
Dedicated SaaS read-only credential. It cannot publish, modify, disable,
|
||||
rollback, or access Cell management.
|
||||
parameters:
|
||||
TrunkId:
|
||||
name: trunk_id
|
||||
in: path
|
||||
required: true
|
||||
schema: {type: string, pattern: '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'}
|
||||
CellId:
|
||||
name: cell_id
|
||||
in: path
|
||||
required: true
|
||||
schema: {type: string, pattern: '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'}
|
||||
IfMatch:
|
||||
name: If-Match
|
||||
in: header
|
||||
required: true
|
||||
description: Exact latest revision required for CAS; quotes are accepted.
|
||||
schema: {type: integer, minimum: 0}
|
||||
RequestId:
|
||||
name: X-Request-ID
|
||||
in: header
|
||||
required: true
|
||||
schema: {type: string, minLength: 1, maxLength: 128}
|
||||
responses:
|
||||
BadRequest:
|
||||
description: Invalid configuration or request
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/ErrorResponse'}
|
||||
Unauthorized:
|
||||
description: Missing or wrong authentication domain
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/ErrorResponse'}
|
||||
Forbidden:
|
||||
description: Credential lacks the required scope
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/ErrorResponse'}
|
||||
Conflict:
|
||||
description: CAS conflict or no compatible Cell
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/ErrorResponse'}
|
||||
NotFound:
|
||||
description: Resource is not visible or does not exist
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/ErrorResponse'}
|
||||
schemas:
|
||||
Mode:
|
||||
type: string
|
||||
enum: [mock, real]
|
||||
Health:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [status, mode]
|
||||
properties:
|
||||
status: {type: string, const: ok}
|
||||
mode: {$ref: '#/components/schemas/Mode'}
|
||||
CodecProfile:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [allowed, preferred]
|
||||
properties:
|
||||
allowed:
|
||||
type: array
|
||||
minItems: 1
|
||||
uniqueItems: true
|
||||
items: {type: string, enum: [PCMA, PCMU]}
|
||||
preferred: {type: string, enum: [PCMA, PCMU]}
|
||||
SipConfig:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [host, port, transport, auth_mode, register]
|
||||
properties:
|
||||
host: {type: string, minLength: 1, maxLength: 253}
|
||||
port: {type: integer, minimum: 1, maximum: 65535}
|
||||
transport: {type: string, enum: [udp, tcp, tls]}
|
||||
auth_mode: {type: string, enum: [ip, digest]}
|
||||
register: {type: boolean}
|
||||
credential_ref:
|
||||
type: string
|
||||
writeOnly: true
|
||||
description: >-
|
||||
Secret-store reference only; plaintext credentials are forbidden.
|
||||
TrunkConfig:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required:
|
||||
- display_name
|
||||
- enabled
|
||||
- sip
|
||||
- codec_profile
|
||||
- caller_ids
|
||||
- dial_prefix
|
||||
- egress_pool_id
|
||||
- max_concurrency
|
||||
- max_cps
|
||||
properties:
|
||||
display_name: {type: string, minLength: 1, maxLength: 256}
|
||||
enabled: {type: boolean}
|
||||
sip: {$ref: '#/components/schemas/SipConfig'}
|
||||
codec_profile: {$ref: '#/components/schemas/CodecProfile'}
|
||||
caller_ids:
|
||||
type: array
|
||||
minItems: 1
|
||||
uniqueItems: true
|
||||
items: {type: string, minLength: 1, maxLength: 128}
|
||||
dial_prefix: {type: string, maxLength: 32}
|
||||
egress_pool_id:
|
||||
type: string
|
||||
pattern: '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
|
||||
max_concurrency: {type: integer, minimum: 1}
|
||||
max_cps: {type: integer, minimum: 1}
|
||||
CellConfig:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [egress_pool_id, codec_capabilities, status, max_concurrency]
|
||||
properties:
|
||||
egress_pool_id:
|
||||
type: string
|
||||
pattern: '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
|
||||
codec_capabilities:
|
||||
type: array
|
||||
minItems: 1
|
||||
uniqueItems: true
|
||||
items: {type: string, enum: [PCMA, PCMU]}
|
||||
status: {type: string, enum: [healthy, draining, disabled]}
|
||||
max_concurrency: {type: integer, minimum: 1}
|
||||
management_url:
|
||||
type: string
|
||||
format: uri
|
||||
pattern: '^https://'
|
||||
description: >-
|
||||
mTLS Cell Agent endpoint. Required when mode=real; credentials and
|
||||
query strings are not allowed.
|
||||
RevisionInfo:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [revision, state, created_at, created_by]
|
||||
properties:
|
||||
revision: {type: integer, minimum: 1}
|
||||
state: {type: string, enum: [draft, publishing, published, superseded]}
|
||||
created_at: {type: string, format: date-time}
|
||||
created_by: {type: string}
|
||||
AdminTrunk:
|
||||
type: object
|
||||
required:
|
||||
- mode
|
||||
- trunk_id
|
||||
- latest_revision
|
||||
- active_revision
|
||||
- status
|
||||
- compatible_cell_ids
|
||||
- latest
|
||||
- active
|
||||
- versions
|
||||
properties:
|
||||
mode: {$ref: '#/components/schemas/Mode'}
|
||||
trunk_id: {type: string}
|
||||
latest_revision: {type: integer, minimum: 1}
|
||||
active_revision: {type: integer, minimum: 0}
|
||||
status: {type: string, enum: [draft, published, disabled]}
|
||||
updated_at: {type: string, format: date-time}
|
||||
compatible_cell_ids: {type: array, items: {type: string}}
|
||||
latest: {$ref: '#/components/schemas/TrunkView'}
|
||||
active: {$ref: '#/components/schemas/TrunkView'}
|
||||
versions:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/RevisionInfo'
|
||||
TrunkView:
|
||||
allOf:
|
||||
- {$ref: '#/components/schemas/TrunkConfig'}
|
||||
- type: object
|
||||
properties:
|
||||
trunk_id: {type: string}
|
||||
credential_configured: {type: boolean}
|
||||
asterisk_allow:
|
||||
type: array
|
||||
items: {type: string, enum: [alaw, ulaw]}
|
||||
ReadonlyTrunk:
|
||||
type: object
|
||||
required:
|
||||
- mode
|
||||
- trunk_id
|
||||
- revision
|
||||
- status
|
||||
- config
|
||||
properties:
|
||||
mode: {$ref: '#/components/schemas/Mode'}
|
||||
trunk_id: {type: string}
|
||||
revision: {type: integer, minimum: 1}
|
||||
status: {type: string, const: published}
|
||||
updated_at: {type: string, format: date-time}
|
||||
config: {$ref: '#/components/schemas/TrunkView'}
|
||||
AdminTrunkList:
|
||||
type: object
|
||||
required: [mode, trunks]
|
||||
properties:
|
||||
mode: {$ref: '#/components/schemas/Mode'}
|
||||
trunks: {type: array, items: {$ref: '#/components/schemas/AdminTrunk'}}
|
||||
ReadonlyTrunkList:
|
||||
type: object
|
||||
required: [mode, trunks]
|
||||
properties:
|
||||
mode: {$ref: '#/components/schemas/Mode'}
|
||||
trunks:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/ReadonlyTrunk'
|
||||
Cell:
|
||||
type: object
|
||||
required: [mode, cell_id, revision, config, updated_at, updated_by]
|
||||
properties:
|
||||
mode: {$ref: '#/components/schemas/Mode'}
|
||||
cell_id: {type: string}
|
||||
revision: {type: integer, minimum: 1}
|
||||
config: {$ref: '#/components/schemas/CellConfig'}
|
||||
updated_at: {type: string, format: date-time}
|
||||
updated_by: {type: string}
|
||||
Publication:
|
||||
type: object
|
||||
required: [trunk_id, revision, cell_id, status, updated_at]
|
||||
properties:
|
||||
trunk_id: {type: string}
|
||||
revision: {type: integer, minimum: 1}
|
||||
cell_id: {type: string}
|
||||
status: {type: string, enum: [pending, applied, failed]}
|
||||
error_code: {type: [string, 'null']}
|
||||
updated_at: {type: string, format: date-time}
|
||||
AuditEntry:
|
||||
type: object
|
||||
required:
|
||||
- audit_id
|
||||
- resource_type
|
||||
- resource_id
|
||||
- action
|
||||
- revision
|
||||
- actor
|
||||
- details_json
|
||||
- created_at
|
||||
properties:
|
||||
audit_id: {type: string}
|
||||
resource_type: {type: string, const: trunk}
|
||||
resource_id: {type: string}
|
||||
action:
|
||||
type: string
|
||||
enum:
|
||||
[
|
||||
upsert,
|
||||
publish,
|
||||
publish_failed,
|
||||
disable,
|
||||
disable_failed,
|
||||
rollback,
|
||||
rollback_failed,
|
||||
]
|
||||
revision: {type: integer, minimum: 0}
|
||||
actor: {type: string}
|
||||
request_id: {type: [string, 'null']}
|
||||
details_json: {type: string}
|
||||
created_at: {type: string, format: date-time}
|
||||
ErrorResponse:
|
||||
type: object
|
||||
required: [error]
|
||||
properties:
|
||||
error:
|
||||
type: object
|
||||
required: [code, message]
|
||||
properties:
|
||||
code: {type: string}
|
||||
message: {type: string}
|
||||
Reference in New Issue
Block a user