{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://go-sip.local/contracts/proposals/config-read-v0.3.schema.json", "title": "Project-local F01 contract: read-only configuration responses; external SaaS compatibility unverified", "oneOf": [ {"$ref": "#/$defs/sip_response"}, {"$ref": "#/$defs/task_response"}, {"$ref": "#/$defs/tenant_quota_response"}, {"$ref": "#/$defs/error_response"} ], "$defs": { "sip_response": { "type": "object", "additionalProperties": false, "required": ["schema_version", "resource", "dispatcher_id", "revision", "approved_at", "trunks"], "properties": { "schema_version": {"const": "config-read.v0.3"}, "resource": {"const": "sip_config"}, "dispatcher_id": {"$ref": "#/$defs/dispatcher_id"}, "revision": {"type": "integer", "minimum": 1}, "approved_at": {"type": "string", "format": "date-time"}, "trunks": { "type": "array", "minItems": 1, "maxItems": 32, "items": {"$ref": "#/$defs/trunk"} } } }, "task_response": { "type": "object", "additionalProperties": false, "required": ["schema_version", "resource", "dispatcher_id", "tenant_id", "tenant_key", "task_id", "task_revision", "status", "max_concurrent_calls", "ring_timeout_ms", "max_call_duration_ms", "route_policy_id", "caller_profile_id", "allowed_trunk_ids", "schedule", "agent"], "properties": { "schema_version": {"const": "config-read.v0.1"}, "resource": {"const": "task_config"}, "dispatcher_id": {"$ref": "#/$defs/dispatcher_id"}, "tenant_id": {"type": "string", "minLength": 1, "maxLength": 128}, "tenant_key": {"type": "string", "minLength": 1, "maxLength": 196, "$comment": "Validate <=196 UTF-8 bytes in business logic; preserve the original value and do not place tenant_key in queue/routing names."}, "task_id": {"type": "string", "pattern": "^[A-Za-z0-9_-]{1,128}$"}, "task_revision": {"type": "integer", "minimum": 1}, "status": {"enum": ["running", "paused", "stopped", "finished"]}, "name": {"type": "string", "minLength": 1, "maxLength": 256}, "group_id": {"type": ["string", "null"], "maxLength": 128}, "max_concurrent_calls": {"type": "integer", "minimum": 1}, "ring_timeout_ms": {"type": "integer", "minimum": 1}, "max_call_duration_ms": {"type": "integer", "minimum": 1}, "route_policy_id": {"type": "string", "minLength": 1, "maxLength": 128}, "caller_profile_id": {"type": "string", "minLength": 1, "maxLength": 128}, "allowed_trunk_ids": {"type": "array", "minItems": 1, "maxItems": 32, "uniqueItems": true, "items": {"type": "string", "minLength": 1, "maxLength": 128}}, "schedule": {"$ref": "#/$defs/task_schedule"}, "agent": {"$ref": "#/$defs/agent"} } }, "tenant_quota_response": { "type": "object", "additionalProperties": false, "required": ["schema_version", "resource", "dispatcher_id", "tenant_id", "tenant_key", "quota_revision", "max_concurrent_calls", "valid_until"], "properties": { "schema_version": {"const": "config-read.v0.1"}, "resource": {"const": "tenant_quota"}, "dispatcher_id": {"$ref": "#/$defs/dispatcher_id"}, "tenant_id": {"type": "string", "minLength": 1, "maxLength": 128}, "tenant_key": {"type": "string", "minLength": 1, "maxLength": 196}, "quota_revision": {"type": "integer", "minimum": 1}, "max_concurrent_calls": {"type": "integer", "minimum": 0}, "valid_until": {"type": "string", "format": "date-time"} }, "$comment": "Project-local response: assigned share for this Dispatcher, aggregated across all tasks of the tenant. Validate tenant_id/tenant_key mapping and valid_until in business logic." }, "error_response": { "type": "object", "additionalProperties": false, "required": ["schema_version", "resource", "error"], "properties": { "schema_version": {"const": "config-read.v0.1"}, "resource": {"const": "error"}, "error": { "type": "object", "additionalProperties": false, "required": ["code", "message"], "properties": { "code": {"enum": ["invalid_request", "unauthorized", "dispatcher_not_authorized", "resource_not_found", "tenant_quota_unavailable", "service_unavailable"]}, "message": {"type": "string", "minLength": 1, "maxLength": 256} } } } }, "dispatcher_id": { "type": "string", "format": "uuid", "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$" }, "trunk": { "type": "object", "additionalProperties": false, "required": ["trunk_id", "provider_id", "codec", "dial_prefix", "enabled", "server_host", "server_port", "transport", "auth_mode", "registration_required", "max_concurrent_calls", "caller_profiles", "schedule"], "properties": { "trunk_id": {"type": "string", "minLength": 1, "maxLength": 128}, "provider_id": {"type": "string", "minLength": 1, "maxLength": 128}, "codec": {"const": "PCMA"}, "dial_prefix": {"type": "string", "maxLength": 32}, "enabled": {"type": "boolean"}, "server_host": {"type": "string", "minLength": 1, "maxLength": 255}, "server_port": {"type": "integer", "minimum": 1, "maximum": 65535}, "transport": {"enum": ["udp", "tcp", "tls", null]}, "auth_mode": {"enum": ["ip", "digest", "none", null]}, "registration_required": {"type": ["boolean", "null"]}, "max_concurrent_calls": {"type": ["integer", "null"], "minimum": 1}, "caller_profiles": { "type": "array", "minItems": 1, "maxItems": 32, "items": { "type": "object", "additionalProperties": false, "required": ["caller_profile_id", "caller_id"], "properties": { "caller_profile_id": {"type": "string", "minLength": 1, "maxLength": 128}, "caller_id": {"type": "string", "minLength": 1, "maxLength": 64} } } }, "schedule": {"$ref": "#/$defs/weekly_schedule"} } }, "agent": { "type": "object", "additionalProperties": false, "required": ["agent_version_id", "authorization_id", "authorization_expires_at", "config"], "properties": { "agent_version_id": {"type": "string", "minLength": 1, "maxLength": 128}, "authorization_id": {"type": "string", "minLength": 1, "maxLength": 128}, "authorization_expires_at": {"type": "string", "format": "date-time"}, "config": {"$ref": "https://go-sip.local/contracts/v1/ai-config.schema.json"} } }, "task_schedule": { "type": "object", "additionalProperties": false, "required": ["time_zone", "starts_at", "ends_at", "weekly_windows", "excluded_dates"], "properties": { "time_zone": {"const": "Asia/Shanghai"}, "starts_at": {"type": ["string", "null"], "format": "date-time"}, "ends_at": {"type": ["string", "null"], "format": "date-time"}, "weekly_windows": {"$ref": "#/$defs/weekly_windows"}, "excluded_dates": { "type": "array", "uniqueItems": true, "items": {"type": "string", "format": "date"} } } }, "weekly_schedule": { "type": "object", "additionalProperties": false, "required": ["time_zone", "weekly_windows"], "properties": { "time_zone": {"const": "Asia/Shanghai"}, "weekly_windows": {"$ref": "#/$defs/weekly_windows"} } }, "weekly_windows": { "type": "object", "additionalProperties": false, "required": ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"], "properties": { "monday": {"$ref": "#/$defs/windows"}, "tuesday": {"$ref": "#/$defs/windows"}, "wednesday": {"$ref": "#/$defs/windows"}, "thursday": {"$ref": "#/$defs/windows"}, "friday": {"$ref": "#/$defs/windows"}, "saturday": {"$ref": "#/$defs/windows"}, "sunday": {"$ref": "#/$defs/windows"} } }, "windows": {"type": "array", "items": {"$ref": "#/$defs/window"}, "$comment": "Each window is left-closed/right-open, start < end, and windows within a day must not overlap. Cross-midnight windows are split across two weekdays; 24:00 is allowed only as end."}, "window": { "type": "object", "additionalProperties": false, "required": ["start", "end"], "properties": { "start": {"type": "string", "pattern": "^(?:[01][0-9]|2[0-3]):[0-5][0-9]$"}, "end": {"type": "string", "pattern": "^(?:(?:[01][0-9]|2[0-3]):[0-5][0-9]|24:00)$"} } } } }