{"configuration":{},"description":"SIP/PSTN call translation architecture.","documentation":{},"id":7,"lastModifiedAgent":"structurizr-onpremises/dsl-editor/568f9843-8085-4f58-8410-bc5c066d71b9","lastModifiedDate":"2026-07-02T12:00:24Z","lastModifiedUser":"m.szota@vasco-electronics.com","model":{"people":[{"description":"Starts a translated call.","id":"1","location":"Unspecified","name":"Caller","properties":{"structurizr.dsl.identifier":"caller"},"relationships":[{"description":"Audio","destinationId":"3","id":"63","sourceId":"1","tags":"Relationship","technology":"SIP user interface"}],"tags":"Element,Person"},{"description":"Answers a normal phone call.","id":"2","location":"Unspecified","name":"Callee (PSTN user)","properties":{"structurizr.dsl.identifier":"pstncallee"},"relationships":[{"description":"Answers and speaks","destinationId":"23","id":"64","sourceId":"2","tags":"Relationship","technology":"PSTN/mobile voice"}],"tags":"Element,Person"}],"softwareSystems":[{"description":"SIP caller app.","documentation":{},"id":"3","location":"Unspecified","name":"VoIP Client","properties":{"structurizr.dsl.identifier":"voipclient"},"relationships":[{"description":"Creates accounts, fetches","destinationId":"4","id":"65","sourceId":"3","tags":"Relationship","technology":"HTTPS/WebSocket"},{"description":"JWT auth","destinationId":"5","id":"71","sourceId":"3","tags":"Relationship","technology":"HTTPS/WebSocket"},{"description":"Registers generated SIP","destinationId":"54","id":"83","sourceId":"3","tags":"Relationship","technology":"SIP UDP 15060"},{"description":"Registers generated SIP","destinationId":"27","id":"84","linkedRelationshipId":"83","sourceId":"3","technology":"SIP UDP 15060"},{"description":"Audio","destinationId":"54","id":"85","sourceId":"3","tags":"Relationship","technology":"RTP UDP"},{"description":"Creates/reads accounts through","destinationId":"7","id":"111","sourceId":"3","tags":"Relationship","technology":"HTTPS"},{"description":"Fetches confirmed SIP","destinationId":"8","id":"112","sourceId":"3","tags":"Relationship","technology":"HTTPS"},{"description":"Requests translated call","destinationId":"9","id":"113","sourceId":"3","tags":"Relationship","technology":"HTTPS"}],"tags":"Element,Software System,External"},{"containers":[{"components":[{"description":"JWT + agreement check.","documentation":{},"id":"6","name":"Device Auth","properties":{"structurizr.dsl.identifier":"backendjwtauth"},"tags":"Element,Component","technology":"Api::V2::DevicesController"},{"description":"Account and SIP setup.","documentation":{},"id":"7","name":"Accounts API","properties":{"structurizr.dsl.identifier":"backendaccountscontroller"},"relationships":[{"description":"JWT auth","destinationId":"6","id":"104","sourceId":"7","tags":"Relationship"},{"description":"Creates or updates","destinationId":"11","id":"107","sourceId":"7","tags":"Relationship"},{"description":"Returns account creation/show","destinationId":"3","id":"114","sourceId":"7","tags":"Relationship","technology":"HTTPS"}],"tags":"Element,Component","technology":"AccountsController"},{"description":"Confirmed SIP contacts.","documentation":{},"id":"8","name":"Contacts API","properties":{"structurizr.dsl.identifier":"backendcontactscontroller"},"relationships":[{"description":"JWT auth","destinationId":"6","id":"105","sourceId":"8","tags":"Relationship"},{"description":"Queries confirmed contacts","destinationId":"15","id":"108","sourceId":"8","tags":"Relationship"},{"description":"Returns contact list","destinationId":"3","id":"115","sourceId":"8","tags":"Relationship","technology":"HTTPS"}],"tags":"Element,Component","technology":"ContactsController"},{"description":"Starts call sessions.","documentation":{},"id":"9","name":"Call Init API","properties":{"structurizr.dsl.identifier":"backenddevicecallenginecontroller"},"relationships":[{"description":"JWT auth","destinationId":"6","id":"106","sourceId":"9","tags":"Relationship"},{"description":"Initializes a translated","destinationId":"12","id":"109","sourceId":"9","tags":"Relationship"},{"description":"Return join data","destinationId":"3","id":"116","sourceId":"9","tags":"Relationship","technology":"HTTPS"}],"tags":"Element,Component","technology":"Devices::CallEngine::CallsController"},{"description":"Call engine callbacks.","documentation":{},"id":"10","name":"Events API","properties":{"structurizr.dsl.identifier":"backendcalleventscontroller"},"relationships":[{"description":"Events","destinationId":"13","id":"110","sourceId":"10","tags":"Relationship"}],"tags":"Element,Component","technology":"CallEngine::CallsController"},{"description":"Requests and stores SIP creds.","documentation":{},"id":"11","name":"SIP Provisioning","properties":{"structurizr.dsl.identifier":"backendaccountprovisioning"},"relationships":[{"description":"Requests generated SIP","destinationId":"14","id":"117","sourceId":"11","tags":"Relationship"},{"description":"Persist","destinationId":"15","id":"122","sourceId":"11","tags":"Relationship"},{"description":"Sends confirmation code","destinationId":"18","id":"123","sourceId":"11","tags":"Relationship"}],"tags":"Element,Component","technology":"Accounts::V2::CreateOperation"},{"description":"Validates and creates calls.","documentation":{},"id":"12","name":"Call Initialization","properties":{"structurizr.dsl.identifier":"backendcallinitialization"},"relationships":[{"description":"Validate","destinationId":"15","id":"125","sourceId":"12","tags":"Relationship"},{"description":"Creates call-engine session","destinationId":"14","id":"126","sourceId":"12","tags":"Relationship"}],"tags":"Element,Component","technology":"CallEngine::Calls::InitializeOperation"},{"description":"Updates calls and transcripts.","documentation":{},"id":"13","name":"Event Handler","properties":{"structurizr.dsl.identifier":"backendcalleventhandler"},"relationships":[{"description":"Locks call, validates","destinationId":"15","id":"127","sourceId":"13","tags":"Relationship"},{"description":"Transcript","destinationId":"16","id":"128","sourceId":"13","tags":"Relationship"}],"tags":"Element,Component","technology":"CallEngine::Calls::HandleEventOperation"},{"description":"Faraday internal client.","documentation":{},"id":"14","name":"Call Engine Client","properties":{"structurizr.dsl.identifier":"backendcallengineclient"},"relationships":[{"description":"Calls call-engine internal","destinationId":"28","id":"118","sourceId":"14","tags":"Relationship","technology":"HTTP JSON, bearer token"},{"description":"Calls call-engine internal","destinationId":"27","id":"119","linkedRelationshipId":"118","sourceId":"14","technology":"HTTP JSON, bearer token"}],"tags":"Element,Component","technology":"CallEngine::ApiService"},{"description":"Calls, accounts, messages.","documentation":{},"id":"15","name":"ActiveRecord Models","properties":{"structurizr.dsl.identifier":"backendpersistence"},"relationships":[{"description":"Reads and writes","destinationId":"19","id":"132","sourceId":"15","tags":"Relationship","technology":"ActiveRecord/PostgreSQL"}],"tags":"Element,Component","technology":"ActiveRecord"},{"description":"Client notifications.","documentation":{},"id":"16","name":"Broadcast Service","properties":{"structurizr.dsl.identifier":"backendbroadcastservice"},"relationships":[{"description":"Notify","destinationId":"17","id":"129","sourceId":"16","tags":"Relationship"}],"tags":"Element,Component","technology":"Devices::BroadcastService"},{"description":"WebSocket stream.","documentation":{},"id":"17","name":"Device Channel","properties":{"structurizr.dsl.identifier":"backendactioncable"},"relationships":[{"description":"Publishes/subscribes ActionCable messages","destinationId":"20","id":"130","sourceId":"17","tags":"Relationship","technology":"Redis"},{"description":"Transcript","destinationId":"3","id":"131","sourceId":"17","tags":"Relationship","technology":"WebSocket"}],"tags":"Element,Component","technology":"ActionCable"},{"description":"Confirmation SMS.","documentation":{},"id":"18","name":"SMS Service","properties":{"structurizr.dsl.identifier":"backendsmsservice"},"relationships":[{"description":"Sends SMS","destinationId":"24","id":"124","sourceId":"18","tags":"Relationship","technology":"HTTPS"}],"tags":"Element,Component","technology":"Sms::Service"}],"description":"Device API, callbacks, WebSocket.","documentation":{},"id":"5","name":"Rails API","properties":{"structurizr.dsl.identifier":"backendrailsapi"},"relationships":[{"description":"Transcript","destinationId":"3","id":"72","sourceId":"5","tags":"Relationship","technology":"HTTPS/WebSocket"},{"description":"Persist","destinationId":"19","id":"73","sourceId":"5","tags":"Relationship","technology":"ActiveRecord/PostgreSQL"},{"description":"Uses Redis for","destinationId":"20","id":"74","sourceId":"5","tags":"Relationship","technology":"Redis"},{"description":"Sends account confirmation","destinationId":"24","id":"77","sourceId":"5","tags":"Relationship","technology":"HTTPS"},{"description":"Creates SIP credentials","destinationId":"28","id":"79","sourceId":"5","tags":"Relationship","technology":"HTTP JSON, bearer token"},{"description":"Creates SIP credentials","destinationId":"27","id":"80","linkedRelationshipId":"79","sourceId":"5","technology":"HTTP JSON, bearer token"}],"tags":"Element,Container","technology":"Ruby on Rails, Puma, Faraday, ActionCable"},{"description":"Rails data store.","documentation":{},"id":"19","name":"Business Backend DB","properties":{"structurizr.dsl.identifier":"backenddb"},"tags":"Element,Container,Database","technology":"PostgreSQL"},{"description":"Cable and jobs.","documentation":{},"id":"20","name":"Backend Redis","properties":{"structurizr.dsl.identifier":"backendredis"},"tags":"Element,Container,Database","technology":"Redis"},{"description":"Background jobs.","documentation":{},"id":"21","name":"Sidekiq Worker","properties":{"structurizr.dsl.identifier":"backendsidekiq"},"relationships":[{"description":"Consumes and schedules","destinationId":"20","id":"75","sourceId":"21","tags":"Relationship","technology":"Redis"},{"description":"Reads and updates","destinationId":"19","id":"76","sourceId":"21","tags":"Relationship","technology":"ActiveRecord/PostgreSQL"}],"tags":"Element,Container","technology":"Sidekiq, sidekiq-cron"}],"description":"Rails call orchestration backend.","documentation":{},"id":"4","location":"Unspecified","name":"call_translator_backend","properties":{"structurizr.dsl.identifier":"businessbackend"},"relationships":[{"description":"Creates SIP credentials","destinationId":"28","id":"66","sourceId":"4","tags":"Relationship","technology":"HTTP JSON, bearer token"},{"description":"Creates SIP credentials","destinationId":"27","id":"67","linkedRelationshipId":"66","sourceId":"4","technology":"HTTP JSON, bearer token"},{"description":"Returns generated SIP","destinationId":"3","id":"70","sourceId":"4","tags":"Relationship","technology":"HTTPS"},{"description":"Sends account confirmation","destinationId":"24","id":"78","linkedRelationshipId":"77","sourceId":"4","technology":"HTTPS"},{"description":"Calls internal API","destinationId":"29","id":"102","sourceId":"4","tags":"Relationship","technology":"HTTP JSON, bearer token"}],"tags":"Element,Software System,External"},{"description":"PSTN SIP trunk.","documentation":{},"id":"22","location":"Unspecified","name":"Outbound SIP Trunk Provider","properties":{"structurizr.dsl.identifier":"siptrunkprovider"},"relationships":[{"description":"Route","destinationId":"23","id":"88","sourceId":"22","tags":"Relationship","technology":"SIP/PSTN interconnect"},{"description":"Propagates callee answer","destinationId":"54","id":"90","sourceId":"22","tags":"Relationship","technology":"SIP/RTP"},{"description":"Propagates callee answer","destinationId":"27","id":"91","linkedRelationshipId":"90","sourceId":"22","technology":"SIP/RTP"}],"tags":"Element,Software System,External"},{"description":"Phone network.","documentation":{},"id":"23","location":"Unspecified","name":"PSTN / Mobile Network","properties":{"structurizr.dsl.identifier":"pstnnetwork"},"relationships":[{"description":"Propagates answer, release","destinationId":"22","id":"89","sourceId":"23","tags":"Relationship","technology":"PSTN/SIP interconnect"},{"description":"Route","destinationId":"2","id":"92","sourceId":"23","tags":"Relationship","technology":"PSTN/mobile voice"}],"tags":"Element,Software System,External"},{"description":"Confirmation SMS.","documentation":{},"id":"24","location":"Unspecified","name":"EmailLabs SMS Gateway","properties":{"structurizr.dsl.identifier":"smsgateway"},"tags":"Element,Software System,External"},{"description":"ASR and TTS.","documentation":{},"id":"25","location":"Unspecified","name":"Azure Speech","properties":{"structurizr.dsl.identifier":"azurespeech"},"tags":"Element,Software System,External"},{"description":"Text translation.","documentation":{},"id":"26","location":"Unspecified","name":"Translation API","properties":{"structurizr.dsl.identifier":"translationapi"},"tags":"Element,Software System,External"},{"containers":[{"components":[{"description":"Internal HTTP routes.","documentation":{},"id":"29","name":"Internal Backend API","properties":{"structurizr.dsl.identifier":"backendapi"},"relationships":[{"description":"Returns internal API","destinationId":"4","id":"103","sourceId":"29","tags":"Relationship","technology":"HTTP JSON"},{"description":"JWT auth","destinationId":"30","id":"135","sourceId":"29","tags":"Relationship"},{"description":"Create SIP creds","destinationId":"31","id":"136","sourceId":"29","tags":"Relationship"},{"description":"Delegates /internal/sessions commands","destinationId":"33","id":"137","sourceId":"29","tags":"Relationship"}],"tags":"Element,Component","technology":"BackendApiController"},{"description":"Token check.","documentation":{},"id":"30","name":"Bearer Auth","properties":{"structurizr.dsl.identifier":"apiauthenticator"},"tags":"Element,Component","technology":"BackendApiAuthenticator"},{"description":"Generates SIP users.","documentation":{},"id":"31","name":"SIP Credentials","properties":{"structurizr.dsl.identifier":"sipcredentialservice"},"relationships":[{"description":"Persist","destinationId":"32","id":"138","sourceId":"31","tags":"Relationship"}],"tags":"Element,Component","technology":"SipCredentialService"},{"description":"Writes PJSIP rows.","documentation":{},"id":"32","name":"Realtime SIP Repo","properties":{"structurizr.dsl.identifier":"sipcredentialrepository"},"relationships":[{"description":"Dial PSTN","destinationId":"62","id":"139","sourceId":"32","tags":"Relationship","technology":"JDBC"}],"tags":"Element,Component","technology":"JdbcSipCredentialRepository"},{"description":"Creates sessions.","documentation":{},"id":"33","name":"Session Service","properties":{"structurizr.dsl.identifier":"sessioncommandservice"},"relationships":[{"description":"Return SIP creds","destinationId":"34","id":"140","sourceId":"33","tags":"Relationship"},{"description":"Creates, reads,","destinationId":"36","id":"141","sourceId":"33","tags":"Relationship"},{"description":"Generates expiring join","destinationId":"35","id":"142","sourceId":"33","tags":"Relationship"},{"description":"Delete session","destinationId":"39","id":"143","sourceId":"33","tags":"Relationship"}],"tags":"Element,Component","technology":"SessionCommandService"},{"description":"Builds callee endpoint.","documentation":{},"id":"34","name":"Request Mapper","properties":{"structurizr.dsl.identifier":"sessionrequestmapper"},"tags":"Element,Component","technology":"SessionRequestMapper"},{"description":"Issues and validates tokens.","documentation":{},"id":"35","name":"Join Tokens","properties":{"structurizr.dsl.identifier":"jointokenservice"},"tags":"Element,Component","technology":"JoinTokenService"},{"description":"Active call state.","documentation":{},"id":"36","name":"Session Registry","properties":{"structurizr.dsl.identifier":"activesessionregistry"},"tags":"Element,Component","technology":"ActiveSessionRegistry"},{"description":"WebSocket listener.","documentation":{},"id":"37","name":"ARI Events","properties":{"structurizr.dsl.identifier":"arieventstream"},"relationships":[{"description":"Parses inbound ARI","destinationId":"38","id":"144","sourceId":"37","tags":"Relationship"}],"tags":"Element,Component","technology":"AriEventStream"},{"description":"Event parser.","documentation":{},"id":"38","name":"ARI Parser","properties":{"structurizr.dsl.identifier":"arieventparser"},"relationships":[{"description":"Events","destinationId":"39","id":"145","sourceId":"38","tags":"Relationship"}],"tags":"Element,Component","technology":"AriEventParser"},{"description":"Bridge and originate.","documentation":{},"id":"39","name":"ARI Call Flow","properties":{"structurizr.dsl.identifier":"aricallflowcontroller"},"relationships":[{"description":"Validate","destinationId":"35","id":"146","sourceId":"39","tags":"Relationship"},{"description":"Binds caller/callee channels","destinationId":"36","id":"147","sourceId":"39","tags":"Relationship"},{"description":"Dial PSTN","destinationId":"40","id":"148","sourceId":"39","tags":"Relationship"},{"description":"Starts bidirectional taps","destinationId":"41","id":"149","sourceId":"39","tags":"Relationship"},{"description":"Cleans up failed","destinationId":"43","id":"150","sourceId":"39","tags":"Relationship"},{"description":"Events","destinationId":"53","id":"151","sourceId":"39","tags":"Relationship"}],"tags":"Element,Component","technology":"AriCallFlowController"},{"description":"ARI HTTP client.","documentation":{},"id":"40","name":"ARI Gateway","properties":{"structurizr.dsl.identifier":"arigateway"},"relationships":[{"description":"Sends ARI HTTP","destinationId":"54","id":"177","sourceId":"40","tags":"Relationship","technology":"ARI HTTP"},{"description":"Controls channels that","destinationId":"57","id":"184","sourceId":"40","tags":"Relationship","technology":"ARI HTTP"},{"description":"Creates bridge, answers","destinationId":"58","id":"186","sourceId":"40","tags":"Relationship","technology":"ARI HTTP"}],"tags":"Element,Component","technology":"AriHttpClient"},{"description":"Snoop and external media.","documentation":{},"id":"41","name":"Media Taps","properties":{"structurizr.dsl.identifier":"mediatapservice"},"relationships":[{"description":"Creates snoop channels","destinationId":"40","id":"152","sourceId":"41","tags":"Relationship"},{"description":"Stores tap bridge","destinationId":"36","id":"153","sourceId":"41","tags":"Relationship"},{"description":"Launches one runner","destinationId":"42","id":"154","sourceId":"41","tags":"Relationship"}],"tags":"Element,Component","technology":"AriMediaTapService"},{"description":"Starts/stops runners.","documentation":{},"id":"42","name":"Runner Coordinator","properties":{"structurizr.dsl.identifier":"runnercoordinator"},"relationships":[{"description":"Runs caller-to-callee media","destinationId":"44","id":"155","sourceId":"42","tags":"Relationship"},{"description":"Runs callee-to-caller media","destinationId":"45","id":"156","sourceId":"42","tags":"Relationship"}],"tags":"Element,Component","technology":"AriConversationRunnerCoordinator"},{"description":"Tears down calls.","documentation":{},"id":"43","name":"Cleanup Service","properties":{"structurizr.dsl.identifier":"cleanupservice"},"relationships":[{"description":"Hangs up channels","destinationId":"40","id":"157","sourceId":"43","tags":"Relationship"},{"description":"Stops conversation runners","destinationId":"42","id":"158","sourceId":"43","tags":"Relationship"},{"description":"Removes active session","destinationId":"36","id":"159","sourceId":"43","tags":"Relationship"},{"description":"Events","destinationId":"53","id":"160","sourceId":"43","tags":"Relationship"}],"tags":"Element,Component","technology":"AriSessionCleanupService"},{"description":"Caller audio path.","documentation":{},"id":"44","name":"Caller -> Callee Runner","properties":{"structurizr.dsl.identifier":"callertocalleerunner"},"relationships":[{"description":"Audio","destinationId":"46","id":"161","sourceId":"44","tags":"Relationship"},{"description":"Audio","destinationId":"47","id":"163","sourceId":"44","tags":"Relationship"}],"tags":"Element,Component","technology":"ConversationRunner"},{"description":"Callee audio path.","documentation":{},"id":"45","name":"Callee -> Caller Runner","properties":{"structurizr.dsl.identifier":"calleetocallerrunner"},"relationships":[{"description":"Audio","destinationId":"46","id":"162","sourceId":"45","tags":"Relationship"},{"description":"Audio","destinationId":"47","id":"164","sourceId":"45","tags":"Relationship"}],"tags":"Element,Component","technology":"ConversationRunner"},{"description":"Receives ulaw RTP.","documentation":{},"id":"46","name":"RTP Receiver","properties":{"structurizr.dsl.identifier":"rtpaudioreceiver"},"tags":"Element,Component","technology":"RtpAudioReceiver"},{"description":"ASR, MT, TTS.","documentation":{},"id":"47","name":"Translation Pipeline","properties":{"structurizr.dsl.identifier":"speechtranslationpipeline"},"relationships":[{"description":"Audio","destinationId":"48","id":"165","sourceId":"47","tags":"Relationship"},{"description":"Translate","destinationId":"49","id":"166","sourceId":"47","tags":"Relationship"},{"description":"Synthesize","destinationId":"50","id":"167","sourceId":"47","tags":"Relationship"},{"description":"Transcript","destinationId":"53","id":"168","sourceId":"47","tags":"Relationship"},{"description":"Registers synthesis request","destinationId":"51","id":"169","sourceId":"47","tags":"Relationship"}],"tags":"Element,Component","technology":"SpeechTranslationPipeline"},{"description":"Speech recognition.","documentation":{},"id":"48","name":"ASR Manager","properties":{"structurizr.dsl.identifier":"recognizermanager"},"relationships":[{"description":"Audio","destinationId":"25","id":"172","sourceId":"48","tags":"Relationship","technology":"Azure Speech SDK"}],"tags":"Element,Component","technology":"RecognizerManager"},{"description":"Text translation.","documentation":{},"id":"49","name":"MT Manager","properties":{"structurizr.dsl.identifier":"translationmanager"},"relationships":[{"description":"Requests translation","destinationId":"26","id":"173","sourceId":"49","tags":"Relationship","technology":"HTTPS JSON"}],"tags":"Element,Component","technology":"TranslationManager"},{"description":"Speech synthesis.","documentation":{},"id":"50","name":"TTS Manager","properties":{"structurizr.dsl.identifier":"synthesizermanager"},"relationships":[{"description":"Requests streaming text-to-speech","destinationId":"25","id":"174","sourceId":"50","tags":"Relationship","technology":"Azure Speech SDK"}],"tags":"Element,Component","technology":"SynthesizerManager"},{"description":"Routes synthesized audio.","documentation":{},"id":"51","name":"Playback Handler","properties":{"structurizr.dsl.identifier":"playbackhandler"},"relationships":[{"description":"Audio","destinationId":"52","id":"170","sourceId":"51","tags":"Relationship"}],"tags":"Element,Component","technology":"SynthesizedPlaybackHandler"},{"description":"Plays generated audio.","documentation":{},"id":"52","name":"ARI Audio Player","properties":{"structurizr.dsl.identifier":"audioplayer"},"relationships":[{"description":"Persist","destinationId":"54","id":"171","sourceId":"52","tags":"Relationship","technology":"Filesystem + ARI HTTP"},{"description":"Creates and deletes","destinationId":"61","id":"193","sourceId":"52","tags":"Relationship","technology":"Filesystem"}],"tags":"Element,Component","technology":"AudioPlayer"},{"description":"Backend callbacks.","documentation":{},"id":"53","name":"Event Publisher","properties":{"structurizr.dsl.identifier":"backendeventpublisher"},"relationships":[{"description":"Events","destinationId":"4","id":"175","sourceId":"53","tags":"Relationship","technology":"HTTP JSON"}],"tags":"Element,Component","technology":"BackendEventPublisher"}],"description":"Session, ARI, media pipeline.","documentation":{},"id":"28","name":"calltranslator Ktor Call Engine","properties":{"structurizr.dsl.identifier":"callengine"},"relationships":[{"description":"Transcript","destinationId":"4","id":"68","sourceId":"28","tags":"Relationship","technology":"HTTP JSON callback"},{"description":"Events","destinationId":"5","id":"81","sourceId":"28","tags":"Relationship","technology":"HTTP JSON, bearer token"},{"description":"Dial PSTN","destinationId":"62","id":"93","sourceId":"28","tags":"Relationship","technology":"JDBC"},{"description":"Events","destinationId":"54","id":"95","sourceId":"28","tags":"Relationship","technology":"ARI HTTP/WebSocket"},{"description":"Audio","destinationId":"25","id":"98","sourceId":"28","tags":"Relationship","technology":"Azure Speech SDK"},{"description":"Translate","destinationId":"26","id":"100","sourceId":"28","tags":"Relationship","technology":"HTTPS JSON"},{"description":"Returns call-engine API","destinationId":"14","id":"120","sourceId":"28","tags":"Relationship","technology":"HTTP JSON"},{"description":"Transcript","destinationId":"10","id":"133","sourceId":"28","tags":"Relationship","technology":"HTTP JSON, bearer token"},{"description":"Controls channels that","destinationId":"57","id":"185","linkedRelationshipId":"184","sourceId":"28","technology":"ARI HTTP"},{"description":"Creates bridge, answers","destinationId":"58","id":"187","linkedRelationshipId":"186","sourceId":"28","technology":"ARI HTTP"},{"description":"Creates and deletes","destinationId":"61","id":"194","linkedRelationshipId":"193","sourceId":"28","technology":"Filesystem"}],"tags":"Element,Container","technology":"Kotlin, Ktor, Coroutines"},{"components":[{"description":"SIP ingress.","documentation":{},"id":"55","name":"PJSIP Stack","properties":{"structurizr.dsl.identifier":"pjsipstack"},"relationships":[{"description":"Looks up caller","destinationId":"62","id":"179","sourceId":"55","tags":"Relationship","technology":"ODBC realtime"},{"description":"Route","destinationId":"56","id":"180","sourceId":"55","tags":"Relationship","technology":"Asterisk dialplan"}],"tags":"Element,Component","technology":"res_pjsip"},{"description":"Extension 700.","documentation":{},"id":"56","name":"Ingress Dialplan","properties":{"structurizr.dsl.identifier":"ingressdialplan"},"relationships":[{"description":"Starts Stasis","destinationId":"57","id":"181","sourceId":"56","tags":"Relationship"}],"tags":"Element,Component","technology":"extensions.conf"},{"description":"ARI app boundary.","documentation":{},"id":"57","name":"Stasis App","properties":{"structurizr.dsl.identifier":"stasisapp"},"relationships":[{"description":"Channel left","destinationId":"37","id":"182","sourceId":"57","tags":"Relationship","technology":"ARI WebSocket"},{"description":"Channel left","destinationId":"28","id":"183","linkedRelationshipId":"182","sourceId":"57","technology":"ARI WebSocket"}],"tags":"Element,Component","technology":"Stasis"},{"description":"Caller/callee bridge.","documentation":{},"id":"58","name":"Call Bridge","properties":{"structurizr.dsl.identifier":"callbridge"},"relationships":[{"description":"Dial PSTN","destinationId":"60","id":"188","sourceId":"58","tags":"Relationship","technology":"PJSIP"},{"description":"Source channels are","destinationId":"59","id":"190","sourceId":"58","tags":"Relationship","technology":"ARI snoop"}],"tags":"Element,Component","technology":"ARI bridge"},{"description":"Snoop + externalMedia.","documentation":{},"id":"59","name":"Media Taps","properties":{"structurizr.dsl.identifier":"mediatapchannels"},"relationships":[{"description":"Audio","destinationId":"46","id":"191","sourceId":"59","tags":"Relationship","technology":"RTP UDP"},{"description":"Audio","destinationId":"28","id":"192","linkedRelationshipId":"191","sourceId":"59","technology":"RTP UDP"}],"tags":"Element,Component","technology":"ARI"},{"description":"Outbound PJSIP trunk.","documentation":{},"id":"60","name":"PSTN Trunk","properties":{"structurizr.dsl.identifier":"outboundtrunk"},"relationships":[{"description":"Dial PSTN","destinationId":"22","id":"189","sourceId":"60","tags":"Relationship","technology":"SIP/RTP"}],"tags":"Element,Component","technology":"PJSIP"},{"description":"Playback files.","documentation":{},"id":"61","name":"Sounds Directory","properties":{"structurizr.dsl.identifier":"soundsdirectory"},"relationships":[{"description":"Provides sound: media","destinationId":"58","id":"195","sourceId":"61","tags":"Relationship","technology":"Asterisk media"}],"tags":"Element,Component","technology":"/var/lib/asterisk/sounds"}],"description":"SIP, ARI, RTP bridge.","documentation":{},"id":"54","name":"Asterisk PBX","properties":{"structurizr.dsl.identifier":"asterisk"},"relationships":[{"description":"Dial PSTN","destinationId":"22","id":"86","sourceId":"54","tags":"Relationship","technology":"SIP/RTP"},{"description":"Dial PSTN","destinationId":"62","id":"94","sourceId":"54","tags":"Relationship","technology":"ODBC realtime"},{"description":"Events","destinationId":"28","id":"96","sourceId":"54","tags":"Relationship","technology":"ARI WebSocket"},{"description":"Bridge + taps","destinationId":"28","id":"97","sourceId":"54","tags":"Relationship","technology":"RTP UDP ulaw"},{"description":"Events","destinationId":"37","id":"176","sourceId":"54","tags":"Relationship","technology":"ARI WebSocket"},{"description":"Audio","destinationId":"46","id":"178","sourceId":"54","tags":"Relationship","technology":"RTP UDP ulaw"}],"tags":"Element,Container","technology":"Asterisk, PJSIP, ARI, RTP, Docker"},{"description":"PJSIP realtime data.","documentation":{},"id":"62","name":"Asterisk Realtime DB","properties":{"structurizr.dsl.identifier":"realtimedb"},"tags":"Element,Container,Database","technology":"PostgreSQL 16"}],"description":"SIP bridge and live translation.","documentation":{},"id":"27","location":"Unspecified","name":"Call Translator PoC","properties":{"structurizr.dsl.identifier":"calltranslator"},"relationships":[{"description":"Transcript","destinationId":"4","id":"69","linkedRelationshipId":"68","sourceId":"27","technology":"HTTP JSON callback"},{"description":"Events","destinationId":"5","id":"82","linkedRelationshipId":"81","sourceId":"27","technology":"HTTP JSON, bearer token"},{"description":"Dial PSTN","destinationId":"22","id":"87","linkedRelationshipId":"86","sourceId":"27","technology":"SIP/RTP"},{"description":"Audio","destinationId":"25","id":"99","linkedRelationshipId":"98","sourceId":"27","technology":"Azure Speech SDK"},{"description":"Translate","destinationId":"26","id":"101","linkedRelationshipId":"100","sourceId":"27","technology":"HTTPS JSON"},{"description":"Returns call-engine API","destinationId":"14","id":"121","linkedRelationshipId":"120","sourceId":"27","technology":"HTTP JSON"},{"description":"Transcript","destinationId":"10","id":"134","linkedRelationshipId":"133","sourceId":"27","technology":"HTTP JSON, bearer token"}],"tags":"Element,Software System"}]},"name":"Call Translator Architecture","properties":{"structurizr.dsl":"d29ya3NwYWNlICJDYWxsIFRyYW5zbGF0b3IgQXJjaGl0ZWN0dXJlIiAiU0lQL1BTVE4gY2FsbCB0cmFuc2xhdGlvbiBhcmNoaXRlY3R1cmUuIiB7CiAgICBtb2RlbCB7CiAgICAgICAgY2FsbGVyID0gcGVyc29uICJDYWxsZXIiICJTdGFydHMgYSB0cmFuc2xhdGVkIGNhbGwuIgogICAgICAgIHBzdG5DYWxsZWUgPSBwZXJzb24gIkNhbGxlZSAoUFNUTiB1c2VyKSIgIkFuc3dlcnMgYSBub3JtYWwgcGhvbmUgY2FsbC4iCgogICAgICAgIHZvaXBDbGllbnQgPSBzb2Z0d2FyZVN5c3RlbSAiVm9JUCBDbGllbnQiICJTSVAgY2FsbGVyIGFwcC4iICJFeHRlcm5hbCIKICAgICAgICBidXNpbmVzc0JhY2tlbmQgPSBzb2Z0d2FyZVN5c3RlbSAiY2FsbF90cmFuc2xhdG9yX2JhY2tlbmQiICJSYWlscyBjYWxsIG9yY2hlc3RyYXRpb24gYmFja2VuZC4iICJFeHRlcm5hbCIgewogICAgICAgICAgICBiYWNrZW5kUmFpbHNBcGkgPSBjb250YWluZXIgIlJhaWxzIEFQSSIgIkRldmljZSBBUEksIGNhbGxiYWNrcywgV2ViU29ja2V0LiIgIlJ1Ynkgb24gUmFpbHMsIFB1bWEsIEZhcmFkYXksIEFjdGlvbkNhYmxlIiB7CiAgICAgICAgICAgICAgICBiYWNrZW5kSnd0QXV0aCA9IGNvbXBvbmVudCAiRGV2aWNlIEF1dGgiICJKV1QgKyBhZ3JlZW1lbnQgY2hlY2suIiAiQXBpOjpWMjo6RGV2aWNlc0NvbnRyb2xsZXIiCiAgICAgICAgICAgICAgICBiYWNrZW5kQWNjb3VudHNDb250cm9sbGVyID0gY29tcG9uZW50ICJBY2NvdW50cyBBUEkiICJBY2NvdW50IGFuZCBTSVAgc2V0dXAuIiAiQWNjb3VudHNDb250cm9sbGVyIgogICAgICAgICAgICAgICAgYmFja2VuZENvbnRhY3RzQ29udHJvbGxlciA9IGNvbXBvbmVudCAiQ29udGFjdHMgQVBJIiAiQ29uZmlybWVkIFNJUCBjb250YWN0cy4iICJDb250YWN0c0NvbnRyb2xsZXIiCiAgICAgICAgICAgICAgICBiYWNrZW5kRGV2aWNlQ2FsbEVuZ2luZUNvbnRyb2xsZXIgPSBjb21wb25lbnQgIkNhbGwgSW5pdCBBUEkiICJTdGFydHMgY2FsbCBzZXNzaW9ucy4iICJEZXZpY2VzOjpDYWxsRW5naW5lOjpDYWxsc0NvbnRyb2xsZXIiCiAgICAgICAgICAgICAgICBiYWNrZW5kQ2FsbEV2ZW50c0NvbnRyb2xsZXIgPSBjb21wb25lbnQgIkV2ZW50cyBBUEkiICJDYWxsIGVuZ2luZSBjYWxsYmFja3MuIiAiQ2FsbEVuZ2luZTo6Q2FsbHNDb250cm9sbGVyIgogICAgICAgICAgICAgICAgYmFja2VuZEFjY291bnRQcm92aXNpb25pbmcgPSBjb21wb25lbnQgIlNJUCBQcm92aXNpb25pbmciICJSZXF1ZXN0cyBhbmQgc3RvcmVzIFNJUCBjcmVkcy4iICJBY2NvdW50czo6VjI6OkNyZWF0ZU9wZXJhdGlvbiIKICAgICAgICAgICAgICAgIGJhY2tlbmRDYWxsSW5pdGlhbGl6YXRpb24gPSBjb21wb25lbnQgIkNhbGwgSW5pdGlhbGl6YXRpb24iICJWYWxpZGF0ZXMgYW5kIGNyZWF0ZXMgY2FsbHMuIiAiQ2FsbEVuZ2luZTo6Q2FsbHM6OkluaXRpYWxpemVPcGVyYXRpb24iCiAgICAgICAgICAgICAgICBiYWNrZW5kQ2FsbEV2ZW50SGFuZGxlciA9IGNvbXBvbmVudCAiRXZlbnQgSGFuZGxlciIgIlVwZGF0ZXMgY2FsbHMgYW5kIHRyYW5zY3JpcHRzLiIgIkNhbGxFbmdpbmU6OkNhbGxzOjpIYW5kbGVFdmVudE9wZXJhdGlvbiIKICAgICAgICAgICAgICAgIGJhY2tlbmRDYWxsRW5naW5lQ2xpZW50ID0gY29tcG9uZW50ICJDYWxsIEVuZ2luZSBDbGllbnQiICJGYXJhZGF5IGludGVybmFsIGNsaWVudC4iICJDYWxsRW5naW5lOjpBcGlTZXJ2aWNlIgogICAgICAgICAgICAgICAgYmFja2VuZFBlcnNpc3RlbmNlID0gY29tcG9uZW50ICJBY3RpdmVSZWNvcmQgTW9kZWxzIiAiQ2FsbHMsIGFjY291bnRzLCBtZXNzYWdlcy4iICJBY3RpdmVSZWNvcmQiCiAgICAgICAgICAgICAgICBiYWNrZW5kQnJvYWRjYXN0U2VydmljZSA9IGNvbXBvbmVudCAiQnJvYWRjYXN0IFNlcnZpY2UiICJDbGllbnQgbm90aWZpY2F0aW9ucy4iICJEZXZpY2VzOjpCcm9hZGNhc3RTZXJ2aWNlIgogICAgICAgICAgICAgICAgYmFja2VuZEFjdGlvbkNhYmxlID0gY29tcG9uZW50ICJEZXZpY2UgQ2hhbm5lbCIgIldlYlNvY2tldCBzdHJlYW0uIiAiQWN0aW9uQ2FibGUiCiAgICAgICAgICAgICAgICBiYWNrZW5kU21zU2VydmljZSA9IGNvbXBvbmVudCAiU01TIFNlcnZpY2UiICJDb25maXJtYXRpb24gU01TLiIgIlNtczo6U2VydmljZSIKICAgICAgICAgICAgfQoKICAgICAgICAgICAgYmFja2VuZERiID0gY29udGFpbmVyICJCdXNpbmVzcyBCYWNrZW5kIERCIiAiUmFpbHMgZGF0YSBzdG9yZS4iICJQb3N0Z3JlU1FMIiB7CiAgICAgICAgICAgICAgICB0YWdzICJEYXRhYmFzZSIKICAgICAgICAgICAgfQogICAgICAgICAgICBiYWNrZW5kUmVkaXMgPSBjb250YWluZXIgIkJhY2tlbmQgUmVkaXMiICJDYWJsZSBhbmQgam9icy4iICJSZWRpcyIgewogICAgICAgICAgICAgICAgdGFncyAiRGF0YWJhc2UiCiAgICAgICAgICAgIH0KICAgICAgICAgICAgYmFja2VuZFNpZGVraXEgPSBjb250YWluZXIgIlNpZGVraXEgV29ya2VyIiAiQmFja2dyb3VuZCBqb2JzLiIgIlNpZGVraXEsIHNpZGVraXEtY3JvbiIKICAgICAgICB9CiAgICAgICAgc2lwVHJ1bmtQcm92aWRlciA9IHNvZnR3YXJlU3lzdGVtICJPdXRib3VuZCBTSVAgVHJ1bmsgUHJvdmlkZXIiICJQU1ROIFNJUCB0cnVuay4iICJFeHRlcm5hbCIKICAgICAgICBwc3RuTmV0d29yayA9IHNvZnR3YXJlU3lzdGVtICJQU1ROIC8gTW9iaWxlIE5ldHdvcmsiICJQaG9uZSBuZXR3b3JrLiIgIkV4dGVybmFsIgogICAgICAgIHNtc0dhdGV3YXkgPSBzb2Z0d2FyZVN5c3RlbSAiRW1haWxMYWJzIFNNUyBHYXRld2F5IiAiQ29uZmlybWF0aW9uIFNNUy4iICJFeHRlcm5hbCIKICAgICAgICBhenVyZVNwZWVjaCA9IHNvZnR3YXJlU3lzdGVtICJBenVyZSBTcGVlY2giICJBU1IgYW5kIFRUUy4iICJFeHRlcm5hbCIKICAgICAgICB0cmFuc2xhdGlvbkFwaSA9IHNvZnR3YXJlU3lzdGVtICJUcmFuc2xhdGlvbiBBUEkiICJUZXh0IHRyYW5zbGF0aW9uLiIgIkV4dGVybmFsIgoKICAgICAgICBjYWxsVHJhbnNsYXRvciA9IHNvZnR3YXJlU3lzdGVtICJDYWxsIFRyYW5zbGF0b3IgUG9DIiAiU0lQIGJyaWRnZSBhbmQgbGl2ZSB0cmFuc2xhdGlvbi4iIHsKICAgICAgICAgICAgY2FsbEVuZ2luZSA9IGNvbnRhaW5lciAiY2FsbHRyYW5zbGF0b3IgS3RvciBDYWxsIEVuZ2luZSIgIlNlc3Npb24sIEFSSSwgbWVkaWEgcGlwZWxpbmUuIiAiS290bGluLCBLdG9yLCBDb3JvdXRpbmVzIiB7CiAgICAgICAgICAgICAgICBiYWNrZW5kQXBpID0gY29tcG9uZW50ICJJbnRlcm5hbCBCYWNrZW5kIEFQSSIgIkludGVybmFsIEhUVFAgcm91dGVzLiIgIkJhY2tlbmRBcGlDb250cm9sbGVyIgogICAgICAgICAgICAgICAgYXBpQXV0aGVudGljYXRvciA9IGNvbXBvbmVudCAiQmVhcmVyIEF1dGgiICJUb2tlbiBjaGVjay4iICJCYWNrZW5kQXBpQXV0aGVudGljYXRvciIKICAgICAgICAgICAgICAgIHNpcENyZWRlbnRpYWxTZXJ2aWNlID0gY29tcG9uZW50ICJTSVAgQ3JlZGVudGlhbHMiICJHZW5lcmF0ZXMgU0lQIHVzZXJzLiIgIlNpcENyZWRlbnRpYWxTZXJ2aWNlIgogICAgICAgICAgICAgICAgc2lwQ3JlZGVudGlhbFJlcG9zaXRvcnkgPSBjb21wb25lbnQgIlJlYWx0aW1lIFNJUCBSZXBvIiAiV3JpdGVzIFBKU0lQIHJvd3MuIiAiSmRiY1NpcENyZWRlbnRpYWxSZXBvc2l0b3J5IgogICAgICAgICAgICAgICAgc2Vzc2lvbkNvbW1hbmRTZXJ2aWNlID0gY29tcG9uZW50ICJTZXNzaW9uIFNlcnZpY2UiICJDcmVhdGVzIHNlc3Npb25zLiIgIlNlc3Npb25Db21tYW5kU2VydmljZSIKICAgICAgICAgICAgICAgIHNlc3Npb25SZXF1ZXN0TWFwcGVyID0gY29tcG9uZW50ICJSZXF1ZXN0IE1hcHBlciIgIkJ1aWxkcyBjYWxsZWUgZW5kcG9pbnQuIiAiU2Vzc2lvblJlcXVlc3RNYXBwZXIiCiAgICAgICAgICAgICAgICBqb2luVG9rZW5TZXJ2aWNlID0gY29tcG9uZW50ICJKb2luIFRva2VucyIgIklzc3VlcyBhbmQgdmFsaWRhdGVzIHRva2Vucy4iICJKb2luVG9rZW5TZXJ2aWNlIgogICAgICAgICAgICAgICAgYWN0aXZlU2Vzc2lvblJlZ2lzdHJ5ID0gY29tcG9uZW50ICJTZXNzaW9uIFJlZ2lzdHJ5IiAiQWN0aXZlIGNhbGwgc3RhdGUuIiAiQWN0aXZlU2Vzc2lvblJlZ2lzdHJ5IgoKICAgICAgICAgICAgICAgIGFyaUV2ZW50U3RyZWFtID0gY29tcG9uZW50ICJBUkkgRXZlbnRzIiAiV2ViU29ja2V0IGxpc3RlbmVyLiIgIkFyaUV2ZW50U3RyZWFtIgogICAgICAgICAgICAgICAgYXJpRXZlbnRQYXJzZXIgPSBjb21wb25lbnQgIkFSSSBQYXJzZXIiICJFdmVudCBwYXJzZXIuIiAiQXJpRXZlbnRQYXJzZXIiCiAgICAgICAgICAgICAgICBhcmlDYWxsRmxvd0NvbnRyb2xsZXIgPSBjb21wb25lbnQgIkFSSSBDYWxsIEZsb3ciICJCcmlkZ2UgYW5kIG9yaWdpbmF0ZS4iICJBcmlDYWxsRmxvd0NvbnRyb2xsZXIiCiAgICAgICAgICAgICAgICBhcmlHYXRld2F5ID0gY29tcG9uZW50ICJBUkkgR2F0ZXdheSIgIkFSSSBIVFRQIGNsaWVudC4iICJBcmlIdHRwQ2xpZW50IgogICAgICAgICAgICAgICAgbWVkaWFUYXBTZXJ2aWNlID0gY29tcG9uZW50ICJNZWRpYSBUYXBzIiAiU25vb3AgYW5kIGV4dGVybmFsIG1lZGlhLiIgIkFyaU1lZGlhVGFwU2VydmljZSIKICAgICAgICAgICAgICAgIHJ1bm5lckNvb3JkaW5hdG9yID0gY29tcG9uZW50ICJSdW5uZXIgQ29vcmRpbmF0b3IiICJTdGFydHMvc3RvcHMgcnVubmVycy4iICJBcmlDb252ZXJzYXRpb25SdW5uZXJDb29yZGluYXRvciIKICAgICAgICAgICAgICAgIGNsZWFudXBTZXJ2aWNlID0gY29tcG9uZW50ICJDbGVhbnVwIFNlcnZpY2UiICJUZWFycyBkb3duIGNhbGxzLiIgIkFyaVNlc3Npb25DbGVhbnVwU2VydmljZSIKCiAgICAgICAgICAgICAgICBjYWxsZXJUb0NhbGxlZVJ1bm5lciA9IGNvbXBvbmVudCAiQ2FsbGVyIC0+IENhbGxlZSBSdW5uZXIiICJDYWxsZXIgYXVkaW8gcGF0aC4iICJDb252ZXJzYXRpb25SdW5uZXIiCiAgICAgICAgICAgICAgICBjYWxsZWVUb0NhbGxlclJ1bm5lciA9IGNvbXBvbmVudCAiQ2FsbGVlIC0+IENhbGxlciBSdW5uZXIiICJDYWxsZWUgYXVkaW8gcGF0aC4iICJDb252ZXJzYXRpb25SdW5uZXIiCiAgICAgICAgICAgICAgICBydHBBdWRpb1JlY2VpdmVyID0gY29tcG9uZW50ICJSVFAgUmVjZWl2ZXIiICJSZWNlaXZlcyB1bGF3IFJUUC4iICJSdHBBdWRpb1JlY2VpdmVyIgogICAgICAgICAgICAgICAgc3BlZWNoVHJhbnNsYXRpb25QaXBlbGluZSA9IGNvbXBvbmVudCAiVHJhbnNsYXRpb24gUGlwZWxpbmUiICJBU1IsIE1ULCBUVFMuIiAiU3BlZWNoVHJhbnNsYXRpb25QaXBlbGluZSIKICAgICAgICAgICAgICAgIHJlY29nbml6ZXJNYW5hZ2VyID0gY29tcG9uZW50ICJBU1IgTWFuYWdlciIgIlNwZWVjaCByZWNvZ25pdGlvbi4iICJSZWNvZ25pemVyTWFuYWdlciIKICAgICAgICAgICAgICAgIHRyYW5zbGF0aW9uTWFuYWdlciA9IGNvbXBvbmVudCAiTVQgTWFuYWdlciIgIlRleHQgdHJhbnNsYXRpb24uIiAiVHJhbnNsYXRpb25NYW5hZ2VyIgogICAgICAgICAgICAgICAgc3ludGhlc2l6ZXJNYW5hZ2VyID0gY29tcG9uZW50ICJUVFMgTWFuYWdlciIgIlNwZWVjaCBzeW50aGVzaXMuIiAiU3ludGhlc2l6ZXJNYW5hZ2VyIgogICAgICAgICAgICAgICAgcGxheWJhY2tIYW5kbGVyID0gY29tcG9uZW50ICJQbGF5YmFjayBIYW5kbGVyIiAiUm91dGVzIHN5bnRoZXNpemVkIGF1ZGlvLiIgIlN5bnRoZXNpemVkUGxheWJhY2tIYW5kbGVyIgogICAgICAgICAgICAgICAgYXVkaW9QbGF5ZXIgPSBjb21wb25lbnQgIkFSSSBBdWRpbyBQbGF5ZXIiICJQbGF5cyBnZW5lcmF0ZWQgYXVkaW8uIiAiQXVkaW9QbGF5ZXIiCiAgICAgICAgICAgICAgICBiYWNrZW5kRXZlbnRQdWJsaXNoZXIgPSBjb21wb25lbnQgIkV2ZW50IFB1Ymxpc2hlciIgIkJhY2tlbmQgY2FsbGJhY2tzLiIgIkJhY2tlbmRFdmVudFB1Ymxpc2hlciIKICAgICAgICAgICAgfQoKICAgICAgICAgICAgYXN0ZXJpc2sgPSBjb250YWluZXIgIkFzdGVyaXNrIFBCWCIgIlNJUCwgQVJJLCBSVFAgYnJpZGdlLiIgIkFzdGVyaXNrLCBQSlNJUCwgQVJJLCBSVFAsIERvY2tlciIgewogICAgICAgICAgICAgICAgcGpzaXBTdGFjayA9IGNvbXBvbmVudCAiUEpTSVAgU3RhY2siICJTSVAgaW5ncmVzcy4iICJyZXNfcGpzaXAiCiAgICAgICAgICAgICAgICBpbmdyZXNzRGlhbHBsYW4gPSBjb21wb25lbnQgIkluZ3Jlc3MgRGlhbHBsYW4iICJFeHRlbnNpb24gNzAwLiIgImV4dGVuc2lvbnMuY29uZiIKICAgICAgICAgICAgICAgIHN0YXNpc0FwcCA9IGNvbXBvbmVudCAiU3Rhc2lzIEFwcCIgIkFSSSBhcHAgYm91bmRhcnkuIiAiU3Rhc2lzIgogICAgICAgICAgICAgICAgY2FsbEJyaWRnZSA9IGNvbXBvbmVudCAiQ2FsbCBCcmlkZ2UiICJDYWxsZXIvY2FsbGVlIGJyaWRnZS4iICJBUkkgYnJpZGdlIgogICAgICAgICAgICAgICAgbWVkaWFUYXBDaGFubmVscyA9IGNvbXBvbmVudCAiTWVkaWEgVGFwcyIgIlNub29wICsgZXh0ZXJuYWxNZWRpYS4iICJBUkkiCiAgICAgICAgICAgICAgICBvdXRib3VuZFRydW5rID0gY29tcG9uZW50ICJQU1ROIFRydW5rIiAiT3V0Ym91bmQgUEpTSVAgdHJ1bmsuIiAiUEpTSVAiCiAgICAgICAgICAgICAgICBzb3VuZHNEaXJlY3RvcnkgPSBjb21wb25lbnQgIlNvdW5kcyBEaXJlY3RvcnkiICJQbGF5YmFjayBmaWxlcy4iICIvdmFyL2xpYi9hc3Rlcmlzay9zb3VuZHMiCiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIHJlYWx0aW1lRGIgPSBjb250YWluZXIgIkFzdGVyaXNrIFJlYWx0aW1lIERCIiAiUEpTSVAgcmVhbHRpbWUgZGF0YS4iICJQb3N0Z3JlU1FMIDE2IiB7CiAgICAgICAgICAgICAgICB0YWdzICJEYXRhYmFzZSIKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgY2FsbGVyIC0+IHZvaXBDbGllbnQgIkF1ZGlvIiAiU0lQIHVzZXIgaW50ZXJmYWNlIgogICAgICAgIHBzdG5DYWxsZWUgLT4gcHN0bk5ldHdvcmsgIkFuc3dlcnMgYW5kIHNwZWFrcyIgIlBTVE4vbW9iaWxlIHZvaWNlIgoKICAgICAgICB2b2lwQ2xpZW50IC0+IGJ1c2luZXNzQmFja2VuZCAiQ3JlYXRlcyBhY2NvdW50cywgZmV0Y2hlcyIgIkhUVFBTL1dlYlNvY2tldCIKICAgICAgICBidXNpbmVzc0JhY2tlbmQgLT4gY2FsbEVuZ2luZSAiQ3JlYXRlcyBTSVAgY3JlZGVudGlhbHMiICJIVFRQIEpTT04sIGJlYXJlciB0b2tlbiIKICAgICAgICBjYWxsRW5naW5lIC0+IGJ1c2luZXNzQmFja2VuZCAiVHJhbnNjcmlwdCIgIkhUVFAgSlNPTiBjYWxsYmFjayIKICAgICAgICBidXNpbmVzc0JhY2tlbmQgLT4gdm9pcENsaWVudCAiUmV0dXJucyBnZW5lcmF0ZWQgU0lQIiAiSFRUUFMiCgogICAgICAgIHZvaXBDbGllbnQgLT4gYmFja2VuZFJhaWxzQXBpICJKV1QgYXV0aCIgIkhUVFBTL1dlYlNvY2tldCIKICAgICAgICBiYWNrZW5kUmFpbHNBcGkgLT4gdm9pcENsaWVudCAiVHJhbnNjcmlwdCIgIkhUVFBTL1dlYlNvY2tldCIKICAgICAgICBiYWNrZW5kUmFpbHNBcGkgLT4gYmFja2VuZERiICJQZXJzaXN0IiAiQWN0aXZlUmVjb3JkL1Bvc3RncmVTUUwiCiAgICAgICAgYmFja2VuZFJhaWxzQXBpIC0+IGJhY2tlbmRSZWRpcyAiVXNlcyBSZWRpcyBmb3IiICJSZWRpcyIKICAgICAgICBiYWNrZW5kU2lkZWtpcSAtPiBiYWNrZW5kUmVkaXMgIkNvbnN1bWVzIGFuZCBzY2hlZHVsZXMiICJSZWRpcyIKICAgICAgICBiYWNrZW5kU2lkZWtpcSAtPiBiYWNrZW5kRGIgIlJlYWRzIGFuZCB1cGRhdGVzIiAiQWN0aXZlUmVjb3JkL1Bvc3RncmVTUUwiCiAgICAgICAgYmFja2VuZFJhaWxzQXBpIC0+IHNtc0dhdGV3YXkgIlNlbmRzIGFjY291bnQgY29uZmlybWF0aW9uIiAiSFRUUFMiCiAgICAgICAgYmFja2VuZFJhaWxzQXBpIC0+IGNhbGxFbmdpbmUgIkNyZWF0ZXMgU0lQIGNyZWRlbnRpYWxzIiAiSFRUUCBKU09OLCBiZWFyZXIgdG9rZW4iCiAgICAgICAgY2FsbEVuZ2luZSAtPiBiYWNrZW5kUmFpbHNBcGkgIkV2ZW50cyIgIkhUVFAgSlNPTiwgYmVhcmVyIHRva2VuIgoKICAgICAgICB2b2lwQ2xpZW50IC0+IGFzdGVyaXNrICJSZWdpc3RlcnMgZ2VuZXJhdGVkIFNJUCIgIlNJUCBVRFAgMTUwNjAiCiAgICAgICAgdm9pcENsaWVudCAtPiBhc3RlcmlzayAiQXVkaW8iICJSVFAgVURQIgogICAgICAgIGFzdGVyaXNrIC0+IHNpcFRydW5rUHJvdmlkZXIgIkRpYWwgUFNUTiIgIlNJUC9SVFAiCiAgICAgICAgc2lwVHJ1bmtQcm92aWRlciAtPiBwc3RuTmV0d29yayAiUm91dGUiICJTSVAvUFNUTiBpbnRlcmNvbm5lY3QiCiAgICAgICAgcHN0bk5ldHdvcmsgLT4gc2lwVHJ1bmtQcm92aWRlciAiUHJvcGFnYXRlcyBhbnN3ZXIsIHJlbGVhc2UiICJQU1ROL1NJUCBpbnRlcmNvbm5lY3QiCiAgICAgICAgc2lwVHJ1bmtQcm92aWRlciAtPiBhc3RlcmlzayAiUHJvcGFnYXRlcyBjYWxsZWUgYW5zd2VyIiAiU0lQL1JUUCIKICAgICAgICBwc3RuTmV0d29yayAtPiBwc3RuQ2FsbGVlICJSb3V0ZSIgIlBTVE4vbW9iaWxlIHZvaWNlIgoKICAgICAgICBjYWxsRW5naW5lIC0+IHJlYWx0aW1lRGIgIkRpYWwgUFNUTiIgIkpEQkMiCiAgICAgICAgYXN0ZXJpc2sgLT4gcmVhbHRpbWVEYiAiRGlhbCBQU1ROIiAiT0RCQyByZWFsdGltZSIKCiAgICAgICAgY2FsbEVuZ2luZSAtPiBhc3RlcmlzayAiRXZlbnRzIiAiQVJJIEhUVFAvV2ViU29ja2V0IgogICAgICAgIGFzdGVyaXNrIC0+IGNhbGxFbmdpbmUgIkV2ZW50cyIgIkFSSSBXZWJTb2NrZXQiCiAgICAgICAgYXN0ZXJpc2sgLT4gY2FsbEVuZ2luZSAiQnJpZGdlICsgdGFwcyIgIlJUUCBVRFAgdWxhdyIKCiAgICAgICAgY2FsbEVuZ2luZSAtPiBhenVyZVNwZWVjaCAiQXVkaW8iICJBenVyZSBTcGVlY2ggU0RLIgogICAgICAgIGNhbGxFbmdpbmUgLT4gdHJhbnNsYXRpb25BcGkgIlRyYW5zbGF0ZSIgIkhUVFBTIEpTT04iCgogICAgICAgIGJ1c2luZXNzQmFja2VuZCAtPiBiYWNrZW5kQXBpICJDYWxscyBpbnRlcm5hbCBBUEkiICJIVFRQIEpTT04sIGJlYXJlciB0b2tlbiIKICAgICAgICBiYWNrZW5kQXBpIC0+IGJ1c2luZXNzQmFja2VuZCAiUmV0dXJucyBpbnRlcm5hbCBBUEkiICJIVFRQIEpTT04iCiAgICAgICAgYmFja2VuZEFjY291bnRzQ29udHJvbGxlciAtPiBiYWNrZW5kSnd0QXV0aCAiSldUIGF1dGgiCiAgICAgICAgYmFja2VuZENvbnRhY3RzQ29udHJvbGxlciAtPiBiYWNrZW5kSnd0QXV0aCAiSldUIGF1dGgiCiAgICAgICAgYmFja2VuZERldmljZUNhbGxFbmdpbmVDb250cm9sbGVyIC0+IGJhY2tlbmRKd3RBdXRoICJKV1QgYXV0aCIKICAgICAgICBiYWNrZW5kQWNjb3VudHNDb250cm9sbGVyIC0+IGJhY2tlbmRBY2NvdW50UHJvdmlzaW9uaW5nICJDcmVhdGVzIG9yIHVwZGF0ZXMiCiAgICAgICAgYmFja2VuZENvbnRhY3RzQ29udHJvbGxlciAtPiBiYWNrZW5kUGVyc2lzdGVuY2UgIlF1ZXJpZXMgY29uZmlybWVkIGNvbnRhY3RzIgogICAgICAgIGJhY2tlbmREZXZpY2VDYWxsRW5naW5lQ29udHJvbGxlciAtPiBiYWNrZW5kQ2FsbEluaXRpYWxpemF0aW9uICJJbml0aWFsaXplcyBhIHRyYW5zbGF0ZWQiCiAgICAgICAgYmFja2VuZENhbGxFdmVudHNDb250cm9sbGVyIC0+IGJhY2tlbmRDYWxsRXZlbnRIYW5kbGVyICJFdmVudHMiCiAgICAgICAgdm9pcENsaWVudCAtPiBiYWNrZW5kQWNjb3VudHNDb250cm9sbGVyICJDcmVhdGVzL3JlYWRzIGFjY291bnRzIHRocm91Z2giICJIVFRQUyIKICAgICAgICB2b2lwQ2xpZW50IC0+IGJhY2tlbmRDb250YWN0c0NvbnRyb2xsZXIgIkZldGNoZXMgY29uZmlybWVkIFNJUCIgIkhUVFBTIgogICAgICAgIHZvaXBDbGllbnQgLT4gYmFja2VuZERldmljZUNhbGxFbmdpbmVDb250cm9sbGVyICJSZXF1ZXN0cyB0cmFuc2xhdGVkIGNhbGwiICJIVFRQUyIKICAgICAgICBiYWNrZW5kQWNjb3VudHNDb250cm9sbGVyIC0+IHZvaXBDbGllbnQgIlJldHVybnMgYWNjb3VudCBjcmVhdGlvbi9zaG93IiAiSFRUUFMiCiAgICAgICAgYmFja2VuZENvbnRhY3RzQ29udHJvbGxlciAtPiB2b2lwQ2xpZW50ICJSZXR1cm5zIGNvbnRhY3QgbGlzdCIgIkhUVFBTIgogICAgICAgIGJhY2tlbmREZXZpY2VDYWxsRW5naW5lQ29udHJvbGxlciAtPiB2b2lwQ2xpZW50ICJSZXR1cm4gam9pbiBkYXRhIiAiSFRUUFMiCiAgICAgICAgYmFja2VuZEFjY291bnRQcm92aXNpb25pbmcgLT4gYmFja2VuZENhbGxFbmdpbmVDbGllbnQgIlJlcXVlc3RzIGdlbmVyYXRlZCBTSVAiCiAgICAgICAgYmFja2VuZENhbGxFbmdpbmVDbGllbnQgLT4gY2FsbEVuZ2luZSAiQ2FsbHMgY2FsbC1lbmdpbmUgaW50ZXJuYWwiICJIVFRQIEpTT04sIGJlYXJlciB0b2tlbiIKICAgICAgICBjYWxsRW5naW5lIC0+IGJhY2tlbmRDYWxsRW5naW5lQ2xpZW50ICJSZXR1cm5zIGNhbGwtZW5naW5lIEFQSSIgIkhUVFAgSlNPTiIKICAgICAgICBiYWNrZW5kQWNjb3VudFByb3Zpc2lvbmluZyAtPiBiYWNrZW5kUGVyc2lzdGVuY2UgIlBlcnNpc3QiCiAgICAgICAgYmFja2VuZEFjY291bnRQcm92aXNpb25pbmcgLT4gYmFja2VuZFNtc1NlcnZpY2UgIlNlbmRzIGNvbmZpcm1hdGlvbiBjb2RlIgogICAgICAgIGJhY2tlbmRTbXNTZXJ2aWNlIC0+IHNtc0dhdGV3YXkgIlNlbmRzIFNNUyIgIkhUVFBTIgogICAgICAgIGJhY2tlbmRDYWxsSW5pdGlhbGl6YXRpb24gLT4gYmFja2VuZFBlcnNpc3RlbmNlICJWYWxpZGF0ZSIKICAgICAgICBiYWNrZW5kQ2FsbEluaXRpYWxpemF0aW9uIC0+IGJhY2tlbmRDYWxsRW5naW5lQ2xpZW50ICJDcmVhdGVzIGNhbGwtZW5naW5lIHNlc3Npb24iCiAgICAgICAgYmFja2VuZENhbGxFdmVudEhhbmRsZXIgLT4gYmFja2VuZFBlcnNpc3RlbmNlICJMb2NrcyBjYWxsLCB2YWxpZGF0ZXMiCiAgICAgICAgYmFja2VuZENhbGxFdmVudEhhbmRsZXIgLT4gYmFja2VuZEJyb2FkY2FzdFNlcnZpY2UgIlRyYW5zY3JpcHQiCiAgICAgICAgYmFja2VuZEJyb2FkY2FzdFNlcnZpY2UgLT4gYmFja2VuZEFjdGlvbkNhYmxlICJOb3RpZnkiCiAgICAgICAgYmFja2VuZEFjdGlvbkNhYmxlIC0+IGJhY2tlbmRSZWRpcyAiUHVibGlzaGVzL3N1YnNjcmliZXMgQWN0aW9uQ2FibGUgbWVzc2FnZXMiICJSZWRpcyIKICAgICAgICBiYWNrZW5kQWN0aW9uQ2FibGUgLT4gdm9pcENsaWVudCAiVHJhbnNjcmlwdCIgIldlYlNvY2tldCIKICAgICAgICBiYWNrZW5kUGVyc2lzdGVuY2UgLT4gYmFja2VuZERiICJSZWFkcyBhbmQgd3JpdGVzIiAiQWN0aXZlUmVjb3JkL1Bvc3RncmVTUUwiCiAgICAgICAgY2FsbEVuZ2luZSAtPiBiYWNrZW5kQ2FsbEV2ZW50c0NvbnRyb2xsZXIgIlRyYW5zY3JpcHQiICJIVFRQIEpTT04sIGJlYXJlciB0b2tlbiIKICAgICAgICBiYWNrZW5kQXBpIC0+IGFwaUF1dGhlbnRpY2F0b3IgIkpXVCBhdXRoIgogICAgICAgIGJhY2tlbmRBcGkgLT4gc2lwQ3JlZGVudGlhbFNlcnZpY2UgIkNyZWF0ZSBTSVAgY3JlZHMiCiAgICAgICAgYmFja2VuZEFwaSAtPiBzZXNzaW9uQ29tbWFuZFNlcnZpY2UgIkRlbGVnYXRlcyAvaW50ZXJuYWwvc2Vzc2lvbnMgY29tbWFuZHMiCiAgICAgICAgc2lwQ3JlZGVudGlhbFNlcnZpY2UgLT4gc2lwQ3JlZGVudGlhbFJlcG9zaXRvcnkgIlBlcnNpc3QiCiAgICAgICAgc2lwQ3JlZGVudGlhbFJlcG9zaXRvcnkgLT4gcmVhbHRpbWVEYiAiRGlhbCBQU1ROIiAiSkRCQyIKICAgICAgICBzZXNzaW9uQ29tbWFuZFNlcnZpY2UgLT4gc2Vzc2lvblJlcXVlc3RNYXBwZXIgIlJldHVybiBTSVAgY3JlZHMiCiAgICAgICAgc2Vzc2lvbkNvbW1hbmRTZXJ2aWNlIC0+IGFjdGl2ZVNlc3Npb25SZWdpc3RyeSAiQ3JlYXRlcywgcmVhZHMsIgogICAgICAgIHNlc3Npb25Db21tYW5kU2VydmljZSAtPiBqb2luVG9rZW5TZXJ2aWNlICJHZW5lcmF0ZXMgZXhwaXJpbmcgam9pbiIKICAgICAgICBzZXNzaW9uQ29tbWFuZFNlcnZpY2UgLT4gYXJpQ2FsbEZsb3dDb250cm9sbGVyICJEZWxldGUgc2Vzc2lvbiIKCiAgICAgICAgYXJpRXZlbnRTdHJlYW0gLT4gYXJpRXZlbnRQYXJzZXIgIlBhcnNlcyBpbmJvdW5kIEFSSSIKICAgICAgICBhcmlFdmVudFBhcnNlciAtPiBhcmlDYWxsRmxvd0NvbnRyb2xsZXIgIkV2ZW50cyIKICAgICAgICBhcmlDYWxsRmxvd0NvbnRyb2xsZXIgLT4gam9pblRva2VuU2VydmljZSAiVmFsaWRhdGUiCiAgICAgICAgYXJpQ2FsbEZsb3dDb250cm9sbGVyIC0+IGFjdGl2ZVNlc3Npb25SZWdpc3RyeSAiQmluZHMgY2FsbGVyL2NhbGxlZSBjaGFubmVscyIKICAgICAgICBhcmlDYWxsRmxvd0NvbnRyb2xsZXIgLT4gYXJpR2F0ZXdheSAiRGlhbCBQU1ROIgogICAgICAgIGFyaUNhbGxGbG93Q29udHJvbGxlciAtPiBtZWRpYVRhcFNlcnZpY2UgIlN0YXJ0cyBiaWRpcmVjdGlvbmFsIHRhcHMiCiAgICAgICAgYXJpQ2FsbEZsb3dDb250cm9sbGVyIC0+IGNsZWFudXBTZXJ2aWNlICJDbGVhbnMgdXAgZmFpbGVkIgogICAgICAgIGFyaUNhbGxGbG93Q29udHJvbGxlciAtPiBiYWNrZW5kRXZlbnRQdWJsaXNoZXIgIkV2ZW50cyIKCiAgICAgICAgbWVkaWFUYXBTZXJ2aWNlIC0+IGFyaUdhdGV3YXkgIkNyZWF0ZXMgc25vb3AgY2hhbm5lbHMiCiAgICAgICAgbWVkaWFUYXBTZXJ2aWNlIC0+IGFjdGl2ZVNlc3Npb25SZWdpc3RyeSAiU3RvcmVzIHRhcCBicmlkZ2UiCiAgICAgICAgbWVkaWFUYXBTZXJ2aWNlIC0+IHJ1bm5lckNvb3JkaW5hdG9yICJMYXVuY2hlcyBvbmUgcnVubmVyIgogICAgICAgIHJ1bm5lckNvb3JkaW5hdG9yIC0+IGNhbGxlclRvQ2FsbGVlUnVubmVyICJSdW5zIGNhbGxlci10by1jYWxsZWUgbWVkaWEiCiAgICAgICAgcnVubmVyQ29vcmRpbmF0b3IgLT4gY2FsbGVlVG9DYWxsZXJSdW5uZXIgIlJ1bnMgY2FsbGVlLXRvLWNhbGxlciBtZWRpYSIKICAgICAgICBjbGVhbnVwU2VydmljZSAtPiBhcmlHYXRld2F5ICJIYW5ncyB1cCBjaGFubmVscyIKICAgICAgICBjbGVhbnVwU2VydmljZSAtPiBydW5uZXJDb29yZGluYXRvciAiU3RvcHMgY29udmVyc2F0aW9uIHJ1bm5lcnMiCiAgICAgICAgY2xlYW51cFNlcnZpY2UgLT4gYWN0aXZlU2Vzc2lvblJlZ2lzdHJ5ICJSZW1vdmVzIGFjdGl2ZSBzZXNzaW9uIgogICAgICAgIGNsZWFudXBTZXJ2aWNlIC0+IGJhY2tlbmRFdmVudFB1Ymxpc2hlciAiRXZlbnRzIgoKICAgICAgICBjYWxsZXJUb0NhbGxlZVJ1bm5lciAtPiBydHBBdWRpb1JlY2VpdmVyICJBdWRpbyIKICAgICAgICBjYWxsZWVUb0NhbGxlclJ1bm5lciAtPiBydHBBdWRpb1JlY2VpdmVyICJBdWRpbyIKICAgICAgICBjYWxsZXJUb0NhbGxlZVJ1bm5lciAtPiBzcGVlY2hUcmFuc2xhdGlvblBpcGVsaW5lICJBdWRpbyIKICAgICAgICBjYWxsZWVUb0NhbGxlclJ1bm5lciAtPiBzcGVlY2hUcmFuc2xhdGlvblBpcGVsaW5lICJBdWRpbyIKICAgICAgICBzcGVlY2hUcmFuc2xhdGlvblBpcGVsaW5lIC0+IHJlY29nbml6ZXJNYW5hZ2VyICJBdWRpbyIKICAgICAgICBzcGVlY2hUcmFuc2xhdGlvblBpcGVsaW5lIC0+IHRyYW5zbGF0aW9uTWFuYWdlciAiVHJhbnNsYXRlIgogICAgICAgIHNwZWVjaFRyYW5zbGF0aW9uUGlwZWxpbmUgLT4gc3ludGhlc2l6ZXJNYW5hZ2VyICJTeW50aGVzaXplIgogICAgICAgIHNwZWVjaFRyYW5zbGF0aW9uUGlwZWxpbmUgLT4gYmFja2VuZEV2ZW50UHVibGlzaGVyICJUcmFuc2NyaXB0IgogICAgICAgIHNwZWVjaFRyYW5zbGF0aW9uUGlwZWxpbmUgLT4gcGxheWJhY2tIYW5kbGVyICJSZWdpc3RlcnMgc3ludGhlc2lzIHJlcXVlc3QiCiAgICAgICAgcGxheWJhY2tIYW5kbGVyIC0+IGF1ZGlvUGxheWVyICJBdWRpbyIKICAgICAgICBhdWRpb1BsYXllciAtPiBhc3RlcmlzayAiUGVyc2lzdCIgIkZpbGVzeXN0ZW0gKyBBUkkgSFRUUCIKICAgICAgICByZWNvZ25pemVyTWFuYWdlciAtPiBhenVyZVNwZWVjaCAiQXVkaW8iICJBenVyZSBTcGVlY2ggU0RLIgogICAgICAgIHRyYW5zbGF0aW9uTWFuYWdlciAtPiB0cmFuc2xhdGlvbkFwaSAiUmVxdWVzdHMgdHJhbnNsYXRpb24iICJIVFRQUyBKU09OIgogICAgICAgIHN5bnRoZXNpemVyTWFuYWdlciAtPiBhenVyZVNwZWVjaCAiUmVxdWVzdHMgc3RyZWFtaW5nIHRleHQtdG8tc3BlZWNoIiAiQXp1cmUgU3BlZWNoIFNESyIKICAgICAgICBiYWNrZW5kRXZlbnRQdWJsaXNoZXIgLT4gYnVzaW5lc3NCYWNrZW5kICJFdmVudHMiICJIVFRQIEpTT04iCgogICAgICAgIGFzdGVyaXNrIC0+IGFyaUV2ZW50U3RyZWFtICJFdmVudHMiICJBUkkgV2ViU29ja2V0IgogICAgICAgIGFyaUdhdGV3YXkgLT4gYXN0ZXJpc2sgIlNlbmRzIEFSSSBIVFRQIiAiQVJJIEhUVFAiCiAgICAgICAgYXN0ZXJpc2sgLT4gcnRwQXVkaW9SZWNlaXZlciAiQXVkaW8iICJSVFAgVURQIHVsYXciCiAgICAgICAgcGpzaXBTdGFjayAtPiByZWFsdGltZURiICJMb29rcyB1cCBjYWxsZXIiICJPREJDIHJlYWx0aW1lIgogICAgICAgIHBqc2lwU3RhY2sgLT4gaW5ncmVzc0RpYWxwbGFuICJSb3V0ZSIgIkFzdGVyaXNrIGRpYWxwbGFuIgogICAgICAgIGluZ3Jlc3NEaWFscGxhbiAtPiBzdGFzaXNBcHAgIlN0YXJ0cyBTdGFzaXMiCiAgICAgICAgc3Rhc2lzQXBwIC0+IGFyaUV2ZW50U3RyZWFtICJDaGFubmVsIGxlZnQiICJBUkkgV2ViU29ja2V0IgogICAgICAgIGFyaUdhdGV3YXkgLT4gc3Rhc2lzQXBwICJDb250cm9scyBjaGFubmVscyB0aGF0IiAiQVJJIEhUVFAiCiAgICAgICAgYXJpR2F0ZXdheSAtPiBjYWxsQnJpZGdlICJDcmVhdGVzIGJyaWRnZSwgYW5zd2VycyIgIkFSSSBIVFRQIgogICAgICAgIGNhbGxCcmlkZ2UgLT4gb3V0Ym91bmRUcnVuayAiRGlhbCBQU1ROIiAiUEpTSVAiCiAgICAgICAgb3V0Ym91bmRUcnVuayAtPiBzaXBUcnVua1Byb3ZpZGVyICJEaWFsIFBTVE4iICJTSVAvUlRQIgogICAgICAgIGNhbGxCcmlkZ2UgLT4gbWVkaWFUYXBDaGFubmVscyAiU291cmNlIGNoYW5uZWxzIGFyZSIgIkFSSSBzbm9vcCIKICAgICAgICBtZWRpYVRhcENoYW5uZWxzIC0+IHJ0cEF1ZGlvUmVjZWl2ZXIgIkF1ZGlvIiAiUlRQIFVEUCIKICAgICAgICBhdWRpb1BsYXllciAtPiBzb3VuZHNEaXJlY3RvcnkgIkNyZWF0ZXMgYW5kIGRlbGV0ZXMiICJGaWxlc3lzdGVtIgogICAgICAgIHNvdW5kc0RpcmVjdG9yeSAtPiBjYWxsQnJpZGdlICJQcm92aWRlcyBzb3VuZDogbWVkaWEiICJBc3RlcmlzayBtZWRpYSIKICAgIH0KCiAgICB2aWV3cyB7CiAgICAgICAgc3lzdGVtQ29udGV4dCBjYWxsVHJhbnNsYXRvciAiU3lzdGVtQ29udGV4dCIgewogICAgICAgICAgICBpbmNsdWRlICoKICAgICAgICAgICAgYXV0b2xheW91dCBscgogICAgICAgICAgICBkZXNjcmlwdGlvbiAiRXh0ZXJuYWwgcGVvcGxlIGFuZCBzeXN0ZW1zIGludm9sdmVkIGluIGEgdHJhbnNsYXRlZCBQU1ROIGNhbGwuIgogICAgICAgIH0KCiAgICAgICAgY29udGFpbmVyIGNhbGxUcmFuc2xhdG9yICJDb250YWluZXJzIiB7CiAgICAgICAgICAgIGluY2x1ZGUgKgogICAgICAgICAgICBhdXRvbGF5b3V0IGxyCiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJSdW50aW1lIGNvbnRhaW5lcnMgZm9yIHRoZSBwcm9vZiBvZiBjb25jZXB0IGFuZCB0aGUgcHJvdG9jb2xzIGJldHdlZW4gdGhlbS4iCiAgICAgICAgfQoKICAgICAgICBjb21wb25lbnQgY2FsbEVuZ2luZSAiQ2FsbEVuZ2luZUNvbXBvbmVudHMiIHsKICAgICAgICAgICAgaW5jbHVkZSAqCiAgICAgICAgICAgIGF1dG9sYXlvdXQgbHIKICAgICAgICAgICAgZGVzY3JpcHRpb24gIk1ham9yIEtvdGxpbi9LdG9yIGNhbGwgZW5naW5lIGNvbXBvbmVudHM6IGludGVybmFsIEFQSSwgc2Vzc2lvbi90b2tlbiBzdGF0ZSwgQVJJIGNhbGwgY29udHJvbCwgbWVkaWEgdGFwcywgY29udmVyc2F0aW9uIHBpcGVsaW5lLCBwbGF5YmFjaywgYW5kIGJhY2tlbmQgY2FsbGJhY2tzLiIKICAgICAgICB9CgogICAgICAgIGNvbXBvbmVudCBhc3RlcmlzayAiQXN0ZXJpc2tDb21wb25lbnRzIiB7CiAgICAgICAgICAgIGluY2x1ZGUgKgogICAgICAgICAgICBhdXRvbGF5b3V0IGxyCiAgICAgICAgICAgIGRlc2NyaXB0aW9uICJBc3Rlcmlzay1zaWRlIGNvbXBvbmVudHMgcmVzcG9uc2libGUgZm9yIFNJUCBpbmdyZXNzLCByZWFsdGltZSBQSlNJUCBsb29rdXAsIFN0YXNpcy9BUkkgY29udHJvbCwgYnJpZGdlcywgbWVkaWEgdGFwcywgYW5kIG91dGJvdW5kIFBTVE4gdHJ1bmtpbmcuIgogICAgICAgIH0KCiAgICAgICAgY29udGFpbmVyIGJ1c2luZXNzQmFja2VuZCAiQnVzaW5lc3NCYWNrZW5kQ29udGFpbmVycyIgewogICAgICAgICAgICBpbmNsdWRlICoKICAgICAgICAgICAgYXV0b2xheW91dCBscgogICAgICAgICAgICBkZXNjcmlwdGlvbiAiUmFpbHMgYmFja2VuZCBydW50aW1lIGNvbnRhaW5lcnMgZGlzY292ZXJlZCBmcm9tIC9Vc2Vycy9taWNoYWwvUnVieW1pbmVQcm9qZWN0cy9jYWxsLXRyYW5zbGF0b3ItYmFja2VuZDogUmFpbHMgQVBJLCBQb3N0Z3JlU1FMLCBSZWRpcywgYW5kIFNpZGVraXEuIgogICAgICAgIH0KCiAgICAgICAgY29tcG9uZW50IGJhY2tlbmRSYWlsc0FwaSAiQnVzaW5lc3NCYWNrZW5kQ29tcG9uZW50cyIgewogICAgICAgICAgICBpbmNsdWRlICoKICAgICAgICAgICAgYXV0b2xheW91dCBscgogICAgICAgICAgICBkZXNjcmlwdGlvbiAiUmFpbHMgYmFja2VuZCBjb21wb25lbnRzIGZvciBkZXZpY2UgYXV0aGVudGljYXRpb24sIGFjY291bnQvU0lQIHByb3Zpc2lvbmluZywgY2FsbCBpbml0aWFsaXphdGlvbiwgY2FsbC1lbmdpbmUgZXZlbnQgaGFuZGxpbmcsIHBlcnNpc3RlbmNlLCBTTVMgY29uZmlybWF0aW9uLCBhbmQgQWN0aW9uQ2FibGUgYnJvYWRjYXN0cy4iCiAgICAgICAgfQoKICAgICAgICBkeW5hbWljIGNhbGxUcmFuc2xhdG9yICJQc3RuU2Vzc2lvblNldHVwIiAiQnVzaW5lc3MgYmFja2VuZCBjcmVhdGVzIGEgUFNUTiBjYWxsIHNlc3Npb247IHRoZSBWb0lQIGNsaWVudCBqb2lucyBieSBTSVA7IHRoZSBLdG9yIGVuZ2luZSB2YWxpZGF0ZXMgdGhlIGpvaW4gYW5kIG9yaWdpbmF0ZXMgdGhlIFBTVE4gY2FsbGVlIGxlZy4iIHsKICAgICAgICAgICAgdm9pcENsaWVudCAtPiBidXNpbmVzc0JhY2tlbmQgIkRpYWwgUFNUTiIKICAgICAgICAgICAgYnVzaW5lc3NCYWNrZW5kIC0+IGNhbGxFbmdpbmUgIkNyZWF0ZSBzZXNzaW9uIgogICAgICAgICAgICBjYWxsRW5naW5lIC0+IGJ1c2luZXNzQmFja2VuZCAiUmV0dXJuIGpvaW4gZGF0YSIKICAgICAgICAgICAgYnVzaW5lc3NCYWNrZW5kIC0+IHZvaXBDbGllbnQgIlJldHVybiBqb2luIGRldGFpbHMiCiAgICAgICAgICAgIHZvaXBDbGllbnQgLT4gYXN0ZXJpc2sgIlJFR0lTVEVSIgogICAgICAgICAgICBhc3RlcmlzayAtPiByZWFsdGltZURiICJKV1QgYXV0aCIKICAgICAgICAgICAgdm9pcENsaWVudCAtPiBhc3RlcmlzayAiSU5WSVRFIDcwMCIKICAgICAgICAgICAgYXN0ZXJpc2sgLT4gY2FsbEVuZ2luZSAiU3Rhc2lzU3RhcnQiCiAgICAgICAgICAgIGNhbGxFbmdpbmUgLT4gYXN0ZXJpc2sgIkRpYWwgUFNUTiIKICAgICAgICAgICAgYXN0ZXJpc2sgLT4gc2lwVHJ1bmtQcm92aWRlciAiRGlhbCBQU1ROIgogICAgICAgICAgICBzaXBUcnVua1Byb3ZpZGVyIC0+IHBzdG5OZXR3b3JrICJSb3V0ZSIKICAgICAgICAgICAgcHN0bk5ldHdvcmsgLT4gcHN0bkNhbGxlZSAiUm91dGUiCiAgICAgICAgICAgIHBzdG5DYWxsZWUgLT4gcHN0bk5ldHdvcmsgIkFuc3dlciIKICAgICAgICAgICAgYXN0ZXJpc2sgLT4gY2FsbEVuZ2luZSAiU3Rhc2lzU3RhcnQiCiAgICAgICAgICAgIGNhbGxFbmdpbmUgLT4gYXN0ZXJpc2sgIkFuc3dlciBjYWxsIgogICAgICAgICAgICBjYWxsRW5naW5lIC0+IGJ1c2luZXNzQmFja2VuZCAiRXZlbnRzIgogICAgICAgICAgICBhdXRvbGF5b3V0IGxyCiAgICAgICAgfQoKICAgICAgICBkeW5hbWljIGNhbGxUcmFuc2xhdG9yICJCaWRpcmVjdGlvbmFsTWVkaWFUcmFuc2xhdGlvbiIgIkFmdGVyIHRoZSBicmlkZ2UgaXMgdXAsIEFzdGVyaXNrIHNlbmRzIHR3byBtZWRpYSB0YXBzIHRvIHRoZSBLdG9yIGVuZ2luZTsgZWFjaCBkaXJlY3Rpb24gaXMgcmVjb2duaXplZCwgdHJhbnNsYXRlZCwgc3ludGhlc2l6ZWQsIGFuZCBwbGF5ZWQgdG8gdGhlIG9wcG9zaXRlIHBhcnRpY2lwYW50LiIgewogICAgICAgICAgICBjYWxsRW5naW5lIC0+IGFzdGVyaXNrICJDcmVhdGUgY2FsbGVyIgogICAgICAgICAgICBhc3RlcmlzayAtPiBjYWxsRW5naW5lICJBdWRpbyIKICAgICAgICAgICAgY2FsbEVuZ2luZSAtPiBhenVyZVNwZWVjaCAiUmVjb2duaXplIgogICAgICAgICAgICBjYWxsRW5naW5lIC0+IHRyYW5zbGF0aW9uQXBpICJUcmFuc2xhdGUiCiAgICAgICAgICAgIGNhbGxFbmdpbmUgLT4gYXp1cmVTcGVlY2ggIlN5bnRoZXNpemUiCiAgICAgICAgICAgIGNhbGxFbmdpbmUgLT4gYXN0ZXJpc2sgIkF1ZGlvIgogICAgICAgICAgICBhc3RlcmlzayAtPiBjYWxsRW5naW5lICJBdWRpbyIKICAgICAgICAgICAgY2FsbEVuZ2luZSAtPiBhenVyZVNwZWVjaCAiUmVjb2duaXplIgogICAgICAgICAgICBjYWxsRW5naW5lIC0+IHRyYW5zbGF0aW9uQXBpICJUcmFuc2xhdGUiCiAgICAgICAgICAgIGNhbGxFbmdpbmUgLT4gYXp1cmVTcGVlY2ggIlN5bnRoZXNpemUiCiAgICAgICAgICAgIGNhbGxFbmdpbmUgLT4gYXN0ZXJpc2sgIkF1ZGlvIgogICAgICAgICAgICBjYWxsRW5naW5lIC0+IGJ1c2luZXNzQmFja2VuZCAiVHJhbnNjcmlwdCIKICAgICAgICAgICAgYXV0b2xheW91dCBscgogICAgICAgIH0KCiAgICAgICAgZHluYW1pYyBjYWxsVHJhbnNsYXRvciAiU2Vzc2lvbkNsZWFudXAiICJBbnkgaGFuZ3VwLCBjaGFubmVsIGRlc3RydWN0aW9uLCBmYWlsdXJlLCBvciBleHBsaWNpdCBiYWNrZW5kIHNlc3Npb24gZGVsZXRpb24gY2xlYW5zIHVwIEFSSSByZXNvdXJjZXMgYW5kIGFjdGl2ZSBlbmdpbmUgc3RhdGUuIiB7CiAgICAgICAgICAgIGJ1c2luZXNzQmFja2VuZCAtPiBjYWxsRW5naW5lICJEZWxldGUgc2Vzc2lvbiIKICAgICAgICAgICAgY2FsbEVuZ2luZSAtPiBhc3RlcmlzayAiQ2xlYW51cCIKICAgICAgICAgICAgY2FsbEVuZ2luZSAtPiBhc3RlcmlzayAiQ2xlYW51cCIKICAgICAgICAgICAgcHN0bkNhbGxlZSAtPiBwc3RuTmV0d29yayAiQ2xlYW51cCIKICAgICAgICAgICAgcHN0bk5ldHdvcmsgLT4gc2lwVHJ1bmtQcm92aWRlciAiUmVsZWFzZSBjYWxsIgogICAgICAgICAgICBzaXBUcnVua1Byb3ZpZGVyIC0+IGFzdGVyaXNrICJEaWFsIFBTVE4iCiAgICAgICAgICAgIGFzdGVyaXNrIC0+IGNhbGxFbmdpbmUgIkNoYW5uZWwgbGVmdCIKICAgICAgICAgICAgY2FsbEVuZ2luZSAtPiBhc3RlcmlzayAiQ2xlYW51cCIKICAgICAgICAgICAgY2FsbEVuZ2luZSAtPiBidXNpbmVzc0JhY2tlbmQgIkV2ZW50cyIKICAgICAgICAgICAgYXV0b2xheW91dCBscgogICAgICAgIH0KCiAgICAgICAgZHluYW1pYyBjYWxsRW5naW5lICJDYWxsRW5naW5lQ3JlZGVudGlhbEFuZFBzdG5TZXNzaW9uSW50ZXJuYWxzIiAiS3RvciBjYWxsIGVuZ2luZSBjb21wb25lbnQgaW50ZXJhY3Rpb25zIGZvciBTSVAgY3JlZGVudGlhbCBwcm92aXNpb25pbmcsIFBTVE4gc2Vzc2lvbiBjcmVhdGlvbiwgaW5ib3VuZCBqb2luIHZhbGlkYXRpb24sIGNhbGxlZSBvcmlnaW5hdGlvbiwgYW5kIHN0YXJ0ZWQgY2FsbGJhY2sgcHVibGlzaGluZy4iIHsKICAgICAgICAgICAgYnVzaW5lc3NCYWNrZW5kIC0+IGJhY2tlbmRBcGkgIkNyZWF0ZSBTSVAgY3JlZHMiCiAgICAgICAgICAgIGJhY2tlbmRBcGkgLT4gYXBpQXV0aGVudGljYXRvciAiSldUIGF1dGgiCiAgICAgICAgICAgIGJhY2tlbmRBcGkgLT4gc2lwQ3JlZGVudGlhbFNlcnZpY2UgIkNyZWF0ZSBvciBmZXRjaCIKICAgICAgICAgICAgc2lwQ3JlZGVudGlhbFNlcnZpY2UgLT4gc2lwQ3JlZGVudGlhbFJlcG9zaXRvcnkgIkRpYWwgUFNUTiIKICAgICAgICAgICAgc2lwQ3JlZGVudGlhbFJlcG9zaXRvcnkgLT4gcmVhbHRpbWVEYiAiUGVyc2lzdCIKICAgICAgICAgICAgYnVzaW5lc3NCYWNrZW5kIC0+IGJhY2tlbmRBcGkgIkNyZWF0ZSBzZXNzaW9uIgogICAgICAgICAgICBiYWNrZW5kQXBpIC0+IHNlc3Npb25Db21tYW5kU2VydmljZSAiQ3JlYXRlIGFjdGl2ZSB0cmFuc2xhdG9yIgogICAgICAgICAgICBzZXNzaW9uQ29tbWFuZFNlcnZpY2UgLT4gc2Vzc2lvblJlcXVlc3RNYXBwZXIgIkRpYWwgUFNUTiIKICAgICAgICAgICAgc2Vzc2lvbkNvbW1hbmRTZXJ2aWNlIC0+IGFjdGl2ZVNlc3Npb25SZWdpc3RyeSAiQ3JlYXRlIHNlc3Npb24gc3RhdGUiCiAgICAgICAgICAgIHNlc3Npb25Db21tYW5kU2VydmljZSAtPiBqb2luVG9rZW5TZXJ2aWNlICJHZW5lcmF0ZSBleHBpcmluZyBqb2luIgogICAgICAgICAgICBiYWNrZW5kQXBpIC0+IGJ1c2luZXNzQmFja2VuZCAiUmV0dXJuIGpvaW4gZGF0YSIKICAgICAgICAgICAgYXN0ZXJpc2sgLT4gYXJpRXZlbnRTdHJlYW0gIlN0YXNpc1N0YXJ0IgogICAgICAgICAgICBhcmlFdmVudFN0cmVhbSAtPiBhcmlFdmVudFBhcnNlciAiUGFyc2UgQVJJIEpTT04iCiAgICAgICAgICAgIGFyaUV2ZW50UGFyc2VyIC0+IGFyaUNhbGxGbG93Q29udHJvbGxlciAiRXZlbnRzIgogICAgICAgICAgICBhcmlDYWxsRmxvd0NvbnRyb2xsZXIgLT4gam9pblRva2VuU2VydmljZSAiVmFsaWRhdGUiCiAgICAgICAgICAgIGFyaUNhbGxGbG93Q29udHJvbGxlciAtPiBhY3RpdmVTZXNzaW9uUmVnaXN0cnkgIkJpbmQgY2FsbGVyIGNoYW5uZWwiCiAgICAgICAgICAgIGFyaUNhbGxGbG93Q29udHJvbGxlciAtPiBhcmlHYXRld2F5ICJBbnN3ZXIgY2FsbGVyLCBjcmVhdGUiCiAgICAgICAgICAgIGFyaUdhdGV3YXkgLT4gYXN0ZXJpc2sgIkFSSSBhbnN3ZXIvYnJpZGdlL29yaWdpbmF0ZSBjb21tYW5kcyIKICAgICAgICAgICAgYXJpQ2FsbEZsb3dDb250cm9sbGVyIC0+IGFyaUdhdGV3YXkgIkRpYWwgUFNUTiIKICAgICAgICAgICAgYXN0ZXJpc2sgLT4gYXJpRXZlbnRTdHJlYW0gIlN0YXNpc1N0YXJ0IgogICAgICAgICAgICBhcmlDYWxsRmxvd0NvbnRyb2xsZXIgLT4gYXJpR2F0ZXdheSAiQW5zd2VyIGNhbGwiCiAgICAgICAgICAgIGFyaUNhbGxGbG93Q29udHJvbGxlciAtPiBtZWRpYVRhcFNlcnZpY2UgIkJyaWRnZSArIHRhcHMiCiAgICAgICAgICAgIGFyaUNhbGxGbG93Q29udHJvbGxlciAtPiBiYWNrZW5kRXZlbnRQdWJsaXNoZXIgIkV2ZW50cyIKICAgICAgICAgICAgYmFja2VuZEV2ZW50UHVibGlzaGVyIC0+IGJ1c2luZXNzQmFja2VuZCAiRXZlbnRzIgogICAgICAgICAgICBhdXRvbGF5b3V0IGxyCiAgICAgICAgfQoKICAgICAgICBkeW5hbWljIGNhbGxFbmdpbmUgIkNhbGxFbmdpbmVNZWRpYVRyYW5zbGF0aW9uSW50ZXJuYWxzIiAiS3RvciBjYWxsIGVuZ2luZSBjb21wb25lbnQgaW50ZXJhY3Rpb25zIGZvciB0aGUgdHdvIGRpcmVjdGlvbmFsIFJUUCB0cmFuc2xhdGlvbiBydW5uZXJzLiIgewogICAgICAgICAgICBhcmlDYWxsRmxvd0NvbnRyb2xsZXIgLT4gbWVkaWFUYXBTZXJ2aWNlICJCcmlkZ2UgKyB0YXBzIgogICAgICAgICAgICBtZWRpYVRhcFNlcnZpY2UgLT4gYXJpR2F0ZXdheSAiQ3JlYXRlIGNhbGxlciBzbm9vcCIKICAgICAgICAgICAgbWVkaWFUYXBTZXJ2aWNlIC0+IGFyaUdhdGV3YXkgIkNyZWF0ZSBjYWxsZWUgc25vb3AiCiAgICAgICAgICAgIGFyaUdhdGV3YXkgLT4gYXN0ZXJpc2sgIkluc3RhbGwgc25vb3AvZXh0ZXJuYWwtbWVkaWEgY2hhbm5lbHMiCiAgICAgICAgICAgIG1lZGlhVGFwU2VydmljZSAtPiBhY3RpdmVTZXNzaW9uUmVnaXN0cnkgIlN0b3JlIHRhcCBicmlkZ2UiCiAgICAgICAgICAgIG1lZGlhVGFwU2VydmljZSAtPiBydW5uZXJDb29yZGluYXRvciAiTGF1bmNoIGNhbGxlci10by1jYWxsZWUiCiAgICAgICAgICAgIGFzdGVyaXNrIC0+IHJ0cEF1ZGlvUmVjZWl2ZXIgIkF1ZGlvIgogICAgICAgICAgICBjYWxsZXJUb0NhbGxlZVJ1bm5lciAtPiBzcGVlY2hUcmFuc2xhdGlvblBpcGVsaW5lICJBdWRpbyIKICAgICAgICAgICAgc3BlZWNoVHJhbnNsYXRpb25QaXBlbGluZSAtPiByZWNvZ25pemVyTWFuYWdlciAiUmVjb2duaXplIgogICAgICAgICAgICByZWNvZ25pemVyTWFuYWdlciAtPiBhenVyZVNwZWVjaCAiQXVkaW8iCiAgICAgICAgICAgIHNwZWVjaFRyYW5zbGF0aW9uUGlwZWxpbmUgLT4gdHJhbnNsYXRpb25NYW5hZ2VyICJUcmFuc2xhdGUiCiAgICAgICAgICAgIHRyYW5zbGF0aW9uTWFuYWdlciAtPiB0cmFuc2xhdGlvbkFwaSAiUmVxdWVzdCB0cmFuc2xhdGlvbiIKICAgICAgICAgICAgc3BlZWNoVHJhbnNsYXRpb25QaXBlbGluZSAtPiBzeW50aGVzaXplck1hbmFnZXIgIlN5bnRoZXNpemUiCiAgICAgICAgICAgIHN5bnRoZXNpemVyTWFuYWdlciAtPiBhenVyZVNwZWVjaCAiU3ludGhlc2l6ZSIKICAgICAgICAgICAgc3BlZWNoVHJhbnNsYXRpb25QaXBlbGluZSAtPiBwbGF5YmFja0hhbmRsZXIgIlJlZ2lzdGVyIGNhbGxlZSBwbGF5YmFjayIKICAgICAgICAgICAgcGxheWJhY2tIYW5kbGVyIC0+IGF1ZGlvUGxheWVyICJBdWRpbyIKICAgICAgICAgICAgYXVkaW9QbGF5ZXIgLT4gYXN0ZXJpc2sgIlBlcnNpc3QiCiAgICAgICAgICAgIGFzdGVyaXNrIC0+IHJ0cEF1ZGlvUmVjZWl2ZXIgIkF1ZGlvIgogICAgICAgICAgICBjYWxsZWVUb0NhbGxlclJ1bm5lciAtPiBzcGVlY2hUcmFuc2xhdGlvblBpcGVsaW5lICJBdWRpbyIKICAgICAgICAgICAgc3BlZWNoVHJhbnNsYXRpb25QaXBlbGluZSAtPiByZWNvZ25pemVyTWFuYWdlciAiUmVjb2duaXplIgogICAgICAgICAgICBzcGVlY2hUcmFuc2xhdGlvblBpcGVsaW5lIC0+IHRyYW5zbGF0aW9uTWFuYWdlciAiVHJhbnNsYXRlIgogICAgICAgICAgICBzcGVlY2hUcmFuc2xhdGlvblBpcGVsaW5lIC0+IHN5bnRoZXNpemVyTWFuYWdlciAiU3ludGhlc2l6ZSIKICAgICAgICAgICAgc3BlZWNoVHJhbnNsYXRpb25QaXBlbGluZSAtPiBwbGF5YmFja0hhbmRsZXIgIlJlZ2lzdGVyIGNhbGxlciBwbGF5YmFjayIKICAgICAgICAgICAgcGxheWJhY2tIYW5kbGVyIC0+IGF1ZGlvUGxheWVyICJBdWRpbyIKICAgICAgICAgICAgc3BlZWNoVHJhbnNsYXRpb25QaXBlbGluZSAtPiBiYWNrZW5kRXZlbnRQdWJsaXNoZXIgIlRyYW5zY3JpcHQiCiAgICAgICAgICAgIGJhY2tlbmRFdmVudFB1Ymxpc2hlciAtPiBidXNpbmVzc0JhY2tlbmQgIkV2ZW50cyIKICAgICAgICAgICAgYXV0b2xheW91dCBscgogICAgICAgIH0KCiAgICAgICAgZHluYW1pYyBjYWxsRW5naW5lICJDYWxsRW5naW5lQ2xlYW51cEludGVybmFscyIgIkt0b3IgY2FsbCBlbmdpbmUgY29tcG9uZW50IGludGVyYWN0aW9ucyBmb3IgaGFuZ3VwLCBmYWlsdXJlLCBhbmQgZXhwbGljaXQgYmFja2VuZCBzZXNzaW9uIGRlbGV0aW9uIGNsZWFudXAuIiB7CiAgICAgICAgICAgIGJ1c2luZXNzQmFja2VuZCAtPiBiYWNrZW5kQXBpICJEZWxldGUgc2Vzc2lvbiIKICAgICAgICAgICAgYmFja2VuZEFwaSAtPiBzZXNzaW9uQ29tbWFuZFNlcnZpY2UgIkRlbGV0ZSBhY3RpdmUgc2Vzc2lvbiIKICAgICAgICAgICAgc2Vzc2lvbkNvbW1hbmRTZXJ2aWNlIC0+IGFjdGl2ZVNlc3Npb25SZWdpc3RyeSAiVHJhbnNpdGlvbiBzZXNzaW9uIgogICAgICAgICAgICBzZXNzaW9uQ29tbWFuZFNlcnZpY2UgLT4gYXJpQ2FsbEZsb3dDb250cm9sbGVyICJFbmQgc2Vzc2lvbiIKICAgICAgICAgICAgYXN0ZXJpc2sgLT4gYXJpRXZlbnRTdHJlYW0gIkNoYW5uZWwgbGVmdCIKICAgICAgICAgICAgYXJpRXZlbnRTdHJlYW0gLT4gYXJpRXZlbnRQYXJzZXIgIkV2ZW50cyIKICAgICAgICAgICAgYXJpRXZlbnRQYXJzZXIgLT4gYXJpQ2FsbEZsb3dDb250cm9sbGVyICJFdmVudHMiCiAgICAgICAgICAgIGFyaUNhbGxGbG93Q29udHJvbGxlciAtPiBhY3RpdmVTZXNzaW9uUmVnaXN0cnkgIlZhbGlkYXRlIgogICAgICAgICAgICBhcmlDYWxsRmxvd0NvbnRyb2xsZXIgLT4gY2xlYW51cFNlcnZpY2UgIkNsZWFudXAiCiAgICAgICAgICAgIGNsZWFudXBTZXJ2aWNlIC0+IGFyaUdhdGV3YXkgIkNsZWFudXAiCiAgICAgICAgICAgIGNsZWFudXBTZXJ2aWNlIC0+IGFyaUdhdGV3YXkgIkNsZWFudXAiCiAgICAgICAgICAgIGNsZWFudXBTZXJ2aWNlIC0+IHJ1bm5lckNvb3JkaW5hdG9yICJTdG9wIGNvbnZlcnNhdGlvbiBydW5uZXJzIgogICAgICAgICAgICBjbGVhbnVwU2VydmljZSAtPiBhY3RpdmVTZXNzaW9uUmVnaXN0cnkgIlJlbW92ZSBzZXNzaW9uIGluZGV4ZXMiCiAgICAgICAgICAgIGNsZWFudXBTZXJ2aWNlIC0+IGJhY2tlbmRFdmVudFB1Ymxpc2hlciAiRXZlbnRzIgogICAgICAgICAgICBiYWNrZW5kRXZlbnRQdWJsaXNoZXIgLT4gYnVzaW5lc3NCYWNrZW5kICJFdmVudHMiCiAgICAgICAgICAgIGF1dG9sYXlvdXQgbHIKICAgICAgICB9CgogICAgICAgIGR5bmFtaWMgYmFja2VuZFJhaWxzQXBpICJCdXNpbmVzc0JhY2tlbmRBY2NvdW50UHJvdmlzaW9uaW5nIiAiUmFpbHMgYWNjb3VudCBjcmVhdGlvbiByZXF1ZXN0cyBnZW5lcmF0ZWQgU0lQIGNyZWRlbnRpYWxzIGZyb20gdGhlIEt0b3IgY2FsbCBlbmdpbmUgYW5kIHN0b3JlcyB0aGVtIHdpdGggdGhlIGNhbGxlciBhY2NvdW50LiIgewogICAgICAgICAgICB2b2lwQ2xpZW50IC0+IGJhY2tlbmRBY2NvdW50c0NvbnRyb2xsZXIgIkNyZWF0ZSBhY2NvdW50IgogICAgICAgICAgICBiYWNrZW5kQWNjb3VudHNDb250cm9sbGVyIC0+IGJhY2tlbmRKd3RBdXRoICJKV1QgYXV0aCIKICAgICAgICAgICAgYmFja2VuZEFjY291bnRzQ29udHJvbGxlciAtPiBiYWNrZW5kQWNjb3VudFByb3Zpc2lvbmluZyAiQ3JlYXRlIG9yIHVwZGF0ZSBhY2NvdW50IgogICAgICAgICAgICBiYWNrZW5kQWNjb3VudFByb3Zpc2lvbmluZyAtPiBiYWNrZW5kQ2FsbEVuZ2luZUNsaWVudCAiQ3JlYXRlIFNJUCBjcmVkZW50aWFscyIKICAgICAgICAgICAgYmFja2VuZENhbGxFbmdpbmVDbGllbnQgLT4gY2FsbEVuZ2luZSAiQ3JlYXRlIFNJUCBjcmVkcyIKICAgICAgICAgICAgY2FsbEVuZ2luZSAtPiBiYWNrZW5kQ2FsbEVuZ2luZUNsaWVudCAiUmV0dXJuIGpvaW4gZGF0YSIKICAgICAgICAgICAgYmFja2VuZEFjY291bnRQcm92aXNpb25pbmcgLT4gYmFja2VuZFBlcnNpc3RlbmNlICJQZXJzaXN0IgogICAgICAgICAgICBiYWNrZW5kUGVyc2lzdGVuY2UgLT4gYmFja2VuZERiICJQZXJzaXN0IgogICAgICAgICAgICBiYWNrZW5kQWNjb3VudFByb3Zpc2lvbmluZyAtPiBiYWNrZW5kU21zU2VydmljZSAiU2VuZCBjb25maXJtYXRpb24gY29kZSIKICAgICAgICAgICAgYmFja2VuZFNtc1NlcnZpY2UgLT4gc21zR2F0ZXdheSAiUE9TVCBTTVMgcmVxdWVzdCIKICAgICAgICAgICAgYmFja2VuZEFjY291bnRzQ29udHJvbGxlciAtPiB2b2lwQ2xpZW50ICJSZXR1cm4gYWNjb3VudCBjcmVhdGlvbiIKICAgICAgICAgICAgYXV0b2xheW91dCBscgogICAgICAgIH0KCiAgICAgICAgZHluYW1pYyBiYWNrZW5kUmFpbHNBcGkgIkJ1c2luZXNzQmFja2VuZENhbGxJbml0aWFsaXphdGlvbiIgIlJhaWxzIHZhbGlkYXRlcyBhIGNsaWVudCBjYWxsIHJlcXVlc3QsIGFza3MgdGhlIEt0b3IgY2FsbCBlbmdpbmUgZm9yIGEgc2Vzc2lvbiwgcGVyc2lzdHMgdGhlIGNhbGwsIGFuZCByZXR1cm5zIFNJUCBqb2luIGRldGFpbHMgdG8gdGhlIFZvSVAgY2xpZW50LiIgewogICAgICAgICAgICB2b2lwQ2xpZW50IC0+IGJhY2tlbmREZXZpY2VDYWxsRW5naW5lQ29udHJvbGxlciAiSW5pdCBjYWxsIgogICAgICAgICAgICBiYWNrZW5kRGV2aWNlQ2FsbEVuZ2luZUNvbnRyb2xsZXIgLT4gYmFja2VuZEp3dEF1dGggIkpXVCBhdXRoIgogICAgICAgICAgICBiYWNrZW5kRGV2aWNlQ2FsbEVuZ2luZUNvbnRyb2xsZXIgLT4gYmFja2VuZENhbGxJbml0aWFsaXphdGlvbiAiSW5pdGlhbGl6ZSB0cmFuc2xhdGVkIGNhbGwiCiAgICAgICAgICAgIGJhY2tlbmRDYWxsSW5pdGlhbGl6YXRpb24gLT4gYmFja2VuZFBlcnNpc3RlbmNlICJWYWxpZGF0ZSIKICAgICAgICAgICAgYmFja2VuZFBlcnNpc3RlbmNlIC0+IGJhY2tlbmREYiAiUmVhZCBpZGVudGl0aWVzX2FjY291bnRzLCBjYWxscyIKICAgICAgICAgICAgYmFja2VuZENhbGxJbml0aWFsaXphdGlvbiAtPiBiYWNrZW5kQ2FsbEVuZ2luZUNsaWVudCAiQ3JlYXRlIGNhbGwtZW5naW5lIHNlc3Npb24iCiAgICAgICAgICAgIGJhY2tlbmRDYWxsRW5naW5lQ2xpZW50IC0+IGNhbGxFbmdpbmUgIkNyZWF0ZSBzZXNzaW9uIgogICAgICAgICAgICBjYWxsRW5naW5lIC0+IGJhY2tlbmRDYWxsRW5naW5lQ2xpZW50ICJSZXR1cm4gam9pbiBkYXRhIgogICAgICAgICAgICBiYWNrZW5kQ2FsbEluaXRpYWxpemF0aW9uIC0+IGJhY2tlbmRQZXJzaXN0ZW5jZSAiUmV0dXJuIGpvaW4gZGF0YSIKICAgICAgICAgICAgYmFja2VuZFBlcnNpc3RlbmNlIC0+IGJhY2tlbmREYiAiUGVyc2lzdCIKICAgICAgICAgICAgYmFja2VuZERldmljZUNhbGxFbmdpbmVDb250cm9sbGVyIC0+IHZvaXBDbGllbnQgIlJldHVybiBqb2luIGRhdGEiCiAgICAgICAgICAgIGF1dG9sYXlvdXQgbHIKICAgICAgICB9CgogICAgICAgIGR5bmFtaWMgYmFja2VuZFJhaWxzQXBpICJCdXNpbmVzc0JhY2tlbmRDYWxsRXZlbnRIYW5kbGluZyIgIlJhaWxzIGhhbmRsZXMgY2FsbC1lbmdpbmUgY2FsbGJhY2tzLCB1cGRhdGVzIGNhbGwgc3RhdGUsIHBlcnNpc3RzIHRyYW5zY3JpcHRzLCBhZGp1c3RzIHJlbWFpbmluZyB0aW1lLCBhbmQgcHVzaGVzIG5vdGlmaWNhdGlvbnMgdG8gdGhlIGNsaWVudC4iIHsKICAgICAgICAgICAgY2FsbEVuZ2luZSAtPiBiYWNrZW5kQ2FsbEV2ZW50c0NvbnRyb2xsZXIgIlBvc3QgZXZlbnQiCiAgICAgICAgICAgIGJhY2tlbmRDYWxsRXZlbnRzQ29udHJvbGxlciAtPiBiYWNrZW5kQ2FsbEV2ZW50SGFuZGxlciAiVmFsaWRhdGUiCiAgICAgICAgICAgIGJhY2tlbmRDYWxsRXZlbnRIYW5kbGVyIC0+IGJhY2tlbmRQZXJzaXN0ZW5jZSAiVHJhbnNjcmlwdCIKICAgICAgICAgICAgYmFja2VuZFBlcnNpc3RlbmNlIC0+IGJhY2tlbmREYiAiUGVyc2lzdCIKICAgICAgICAgICAgYmFja2VuZENhbGxFdmVudEhhbmRsZXIgLT4gYmFja2VuZEJyb2FkY2FzdFNlcnZpY2UgIlRyYW5zY3JpcHQiCiAgICAgICAgICAgIGJhY2tlbmRCcm9hZGNhc3RTZXJ2aWNlIC0+IGJhY2tlbmRBY3Rpb25DYWJsZSAiTm90aWZ5IgogICAgICAgICAgICBiYWNrZW5kQWN0aW9uQ2FibGUgLT4gYmFja2VuZFJlZGlzICJQdWJsaXNoIEFjdGlvbkNhYmxlIG1lc3NhZ2UiCiAgICAgICAgICAgIGJhY2tlbmRBY3Rpb25DYWJsZSAtPiB2b2lwQ2xpZW50ICJOb3RpZnkiCiAgICAgICAgICAgIGF1dG9sYXlvdXQgbHIKICAgICAgICB9CgogICAgICAgIHN0eWxlcyB7CiAgICAgICAgICAgIGVsZW1lbnQgIlBlcnNvbiIgewogICAgICAgICAgICAgICAgc2hhcGUgUGVyc29uCiAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kICMwODQyN2IKICAgICAgICAgICAgICAgIGNvbG9yICNmZmZmZmYKICAgICAgICAgICAgfQogICAgICAgICAgICBlbGVtZW50ICJTb2Z0d2FyZSBTeXN0ZW0iIHsKICAgICAgICAgICAgICAgIGJhY2tncm91bmQgIzExNjhiZAogICAgICAgICAgICAgICAgY29sb3IgI2ZmZmZmZgogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsZW1lbnQgIkNvbnRhaW5lciIgewogICAgICAgICAgICAgICAgYmFja2dyb3VuZCAjNDM4ZGQ1CiAgICAgICAgICAgICAgICBjb2xvciAjZmZmZmZmCiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxlbWVudCAiQ29tcG9uZW50IiB7CiAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kICM4NWJiZjAKICAgICAgICAgICAgICAgIGNvbG9yICMwMDAwMDAKICAgICAgICAgICAgfQogICAgICAgICAgICBlbGVtZW50ICJEYXRhYmFzZSIgewogICAgICAgICAgICAgICAgc2hhcGUgQ3lsaW5kZXIKICAgICAgICAgICAgICAgIGJhY2tncm91bmQgIzJmOTVjOAogICAgICAgICAgICAgICAgY29sb3IgI2ZmZmZmZgogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsZW1lbnQgIkV4dGVybmFsIiB7CiAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kICM5OTk5OTkKICAgICAgICAgICAgICAgIGNvbG9yICNmZmZmZmYKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KfQo="},"views":{"componentViews":[{"automaticLayout":{"applied":true,"edgeSeparation":0,"implementation":"Graphviz","nodeSeparation":300,"rankDirection":"LeftRight","rankSeparation":300,"vertices":false},"containerId":"28","description":"Major Kotlin/Ktor call engine components: internal API, session/token state, ARI call control, media taps, conversation pipeline, playback, and backend callbacks.","dimensions":{"height":5909,"width":6890},"elements":[{"id":"4","x":970,"y":701},{"id":"25","x":6220,"y":151},{"id":"26","x":6220,"y":751},{"id":"29","x":220,"y":2039},{"id":"30","x":970,"y":2339},{"id":"31","x":970,"y":2960},{"id":"32","x":1720,"y":3385},{"id":"33","x":970,"y":1739},{"id":"34","x":1720,"y":1260},{"id":"35","x":2470,"y":1568},{"id":"36","x":3220,"y":2185},{"id":"37","x":220,"y":3647},{"id":"38","x":970,"y":3605},{"id":"39","x":1720,"y":2630},{"id":"40","x":3220,"y":3693},{"id":"41","x":2470,"y":3385},{"id":"42","x":3220,"y":3093},{"id":"43","x":2470,"y":2785},{"id":"44","x":3970,"y":3660},{"id":"45","x":3970,"y":3060},{"id":"46","x":4720,"y":3660},{"id":"47","x":4720,"y":3060},{"id":"48","x":5470,"y":2460},{"id":"49","x":5470,"y":3060},{"id":"50","x":5470,"y":1860},{"id":"51","x":5470,"y":3660},{"id":"52","x":6220,"y":3676},{"id":"53","x":5470,"y":1260},{"id":"54","x":3970,"y":4260},{"id":"62","x":4720,"y":4868}],"externalContainerBoundariesVisible":false,"key":"CallEngineComponents","order":3,"relationships":[{"id":"102"},{"id":"103","vertices":[{"x":970,"y":1230}]},{"id":"135"},{"id":"136"},{"id":"137"},{"id":"138"},{"id":"139","vertices":[{"x":2470,"y":3914},{"x":3970,"y":4710}]},{"id":"140"},{"id":"141","vertices":[{"x":2170,"y":1710},{"x":2470,"y":1418},{"x":2920,"y":1418}]},{"id":"142","vertices":[{"x":1720,"y":1943},{"x":2170,"y":1943}]},{"id":"143"},{"id":"144"},{"id":"145"},{"id":"146"},{"id":"147"},{"id":"148","vertices":[{"x":2470,"y":3835}]},{"id":"149"},{"id":"150"},{"id":"151","vertices":[{"x":3220,"y":2035}]},{"id":"152"},{"id":"153","vertices":[{"x":2920,"y":3235}]},{"id":"154"},{"id":"155"},{"id":"156"},{"id":"157"},{"id":"158"},{"id":"159"},{"id":"160","vertices":[{"x":3670,"y":2635},{"x":5170,"y":1960}]},{"id":"161"},{"id":"162"},{"id":"163"},{"id":"164"},{"id":"165"},{"id":"166"},{"id":"167","vertices":[{"x":5170,"y":2835},{"x":5470,"y":2310}]},{"id":"168","vertices":[{"x":5170,"y":2835},{"x":5470,"y":1710}]},{"id":"169"},{"id":"170"},{"id":"171","vertices":[{"x":5920,"y":4110}]},{"id":"172","vertices":[{"x":5920,"y":2310},{"x":6220,"y":601}]},{"id":"173","vertices":[{"x":5920,"y":2910},{"x":6220,"y":1080}]},{"id":"174","vertices":[{"x":5920,"y":1710},{"x":6220,"y":601}]},{"id":"175","vertices":[{"x":4199,"y":805},{"x":2691,"y":805}]},{"id":"176","vertices":[{"x":2699,"y":5622},{"x":1941,"y":5622}]},{"id":"177"},{"id":"178"},{"id":"94"}]},{"automaticLayout":{"applied":true,"edgeSeparation":0,"implementation":"Graphviz","nodeSeparation":300,"rankDirection":"LeftRight","rankSeparation":300,"vertices":false},"containerId":"54","description":"Asterisk-side components responsible for SIP ingress, realtime PJSIP lookup, Stasis/ARI control, bridges, media taps, and outbound PSTN trunking.","dimensions":{"height":2778,"width":3120},"elements":[{"id":"22","x":2579,"y":329},{"id":"28","x":1079,"y":2037},{"id":"55","x":329,"y":1483},{"id":"56","x":1079,"y":1437},{"id":"57","x":1829,"y":1529},{"id":"58","x":1079,"y":837},{"id":"59","x":1829,"y":929},{"id":"60","x":1829,"y":329},{"id":"61","x":329,"y":862},{"id":"62","x":1829,"y":2387}],"externalContainerBoundariesVisible":false,"key":"AsteriskComponents","order":4,"relationships":[{"id":"179","vertices":[{"x":1079,"y":2487}]},{"id":"180"},{"id":"181"},{"id":"183"},{"id":"185"},{"id":"187","vertices":[{"x":1079,"y":2008},{"x":929,"y":1858},{"x":929,"y":1437}]},{"id":"188"},{"id":"189"},{"id":"190"},{"id":"192","vertices":[{"x":1829,"y":1379},{"x":1529,"y":2008}]},{"id":"194","vertices":[{"x":1079,"y":2008},{"x":779,"y":1333}]},{"id":"195"},{"id":"93"}]},{"automaticLayout":{"applied":false,"edgeSeparation":0,"implementation":"Graphviz","nodeSeparation":300,"rankDirection":"LeftRight","rankSeparation":300,"vertices":false},"containerId":"5","description":"Rails backend components for device authentication, account/SIP provisioning, call initialization, call-engine event handling, persistence, SMS confirmation, and ActionCable broadcasts.","elements":[{"id":"3","x":0,"y":0},{"id":"6","x":0,"y":0},{"id":"7","x":0,"y":0},{"id":"8","x":0,"y":0},{"id":"9","x":0,"y":0},{"id":"10","x":0,"y":0},{"id":"11","x":0,"y":0},{"id":"12","x":0,"y":0},{"id":"13","x":0,"y":0},{"id":"14","x":0,"y":0},{"id":"15","x":0,"y":0},{"id":"16","x":0,"y":0},{"id":"17","x":0,"y":0},{"id":"18","x":0,"y":0},{"id":"19","x":0,"y":0},{"id":"20","x":0,"y":0},{"id":"24","x":0,"y":0},{"id":"27","x":0,"y":0}],"externalContainerBoundariesVisible":false,"key":"BusinessBackendComponents","order":6,"relationships":[{"id":"104"},{"id":"105"},{"id":"106"},{"id":"107"},{"id":"108"},{"id":"109"},{"id":"110"},{"id":"111"},{"id":"112"},{"id":"113"},{"id":"114"},{"id":"115"},{"id":"116"},{"id":"117"},{"id":"119"},{"id":"121"},{"id":"122"},{"id":"123"},{"id":"124"},{"id":"125"},{"id":"126"},{"id":"127"},{"id":"128"},{"id":"129"},{"id":"130"},{"id":"131"},{"id":"132"},{"id":"134"},{"id":"84"}]}],"configuration":{"branding":{},"lastSavedView":"PstnSessionSetup","metadataSymbols":"SquareBrackets","styles":{"elements":[{"background":"#08427b","color":"#ffffff","shape":"Person","tag":"Person"},{"background":"#1168bd","color":"#ffffff","tag":"Software System"},{"background":"#438dd5","color":"#ffffff","tag":"Container"},{"background":"#85bbf0","color":"#000000","tag":"Component"},{"background":"#2f95c8","color":"#ffffff","shape":"Cylinder","tag":"Database"},{"background":"#999999","color":"#ffffff","tag":"External"}]},"terminology":{}},"containerViews":[{"automaticLayout":{"applied":true,"edgeSeparation":0,"implementation":"Graphviz","nodeSeparation":300,"rankDirection":"LeftRight","rankSeparation":300,"vertices":false},"description":"Runtime containers for the proof of concept and the protocols between them.","dimensions":{"height":2838,"width":2390},"elements":[{"id":"3","x":329,"y":208},{"id":"4","x":1079,"y":208},{"id":"22","x":329,"y":1625},{"id":"25","x":1079,"y":2317},{"id":"26","x":1079,"y":1717},{"id":"28","x":329,"y":808},{"id":"54","x":1079,"y":808},{"id":"62","x":1829,"y":962}],"externalSoftwareSystemBoundariesVisible":false,"key":"Containers","order":2,"relationships":[{"id":"100"},{"id":"65"},{"id":"66"},{"id":"68"},{"id":"70"},{"id":"83"},{"id":"85"},{"id":"86"},{"id":"90","vertices":[{"x":779,"y":1446}]},{"id":"93","vertices":[{"x":1079,"y":1258},{"x":1529,"y":1258}]},{"id":"94"},{"id":"95"},{"id":"96"},{"id":"97"},{"id":"98","vertices":[{"x":1079,"y":2167}]}],"softwareSystemId":"27"},{"automaticLayout":{"applied":false,"edgeSeparation":0,"implementation":"Graphviz","nodeSeparation":300,"rankDirection":"LeftRight","rankSeparation":300,"vertices":false},"description":"Rails backend runtime containers discovered from /Users/michal/RubymineProjects/call-translator-backend: Rails API, PostgreSQL, Redis, and Sidekiq.","elements":[{"id":"3","x":0,"y":0},{"id":"5","x":0,"y":0},{"id":"19","x":0,"y":0},{"id":"20","x":0,"y":0},{"id":"21","x":0,"y":0},{"id":"24","x":0,"y":0},{"id":"27","x":0,"y":0}],"externalSoftwareSystemBoundariesVisible":false,"key":"BusinessBackendContainers","order":5,"relationships":[{"id":"71"},{"id":"72"},{"id":"73"},{"id":"74"},{"id":"75"},{"id":"76"},{"id":"77"},{"id":"80"},{"id":"82"},{"id":"84"}],"softwareSystemId":"4"}],"dynamicViews":[{"automaticLayout":{"applied":true,"edgeSeparation":0,"implementation":"Graphviz","nodeSeparation":300,"rankDirection":"LeftRight","rankSeparation":300,"vertices":false},"description":"Business backend creates a PSTN call session; the VoIP client joins by SIP; the Ktor engine validates the join and originates the PSTN callee leg.","dimensions":{"height":1512,"width":4550},"elementId":"27","elements":[{"id":"2","x":3950,"y":864},{"id":"3","x":950,"y":914},{"id":"4","x":200,"y":614},{"id":"22","x":2450,"y":914},{"id":"23","x":3200,"y":914},{"id":"28","x":950,"y":314},{"id":"54","x":1700,"y":314},{"id":"62","x":2450,"y":314}],"externalBoundariesVisible":false,"key":"PstnSessionSetup","order":7,"relationships":[{"description":"Dial PSTN","id":"65","order":"1","response":false,"vertices":[{"x":855,"y":774}]},{"description":"Create session","id":"66","order":"2","response":false,"vertices":[{"x":800,"y":614}]},{"description":"Return join data","id":"68","order":"3","response":false,"vertices":[{"x":744,"y":474}]},{"description":"Return join details","id":"70","order":"4","response":false,"vertices":[{"x":744,"y":1053}]},{"description":"REGISTER","id":"83","order":"5","response":false,"vertices":[{"x":1643,"y":881}]},{"description":"JWT auth","id":"94","order":"6","response":false},{"description":"INVITE 700","id":"83","order":"7","response":false,"vertices":[{"x":1456,"y":646}]},{"description":"StasisStart","id":"96","order":"8","response":false,"vertices":[{"x":1550,"y":314}]},{"description":"Dial PSTN","id":"95","order":"9","response":false,"vertices":[{"x":1550,"y":614}]},{"description":"Dial PSTN","id":"86","order":"10","response":false},{"description":"Route","id":"88","order":"11","response":false},{"description":"Route","id":"92","order":"12","response":false,"vertices":[{"x":3787,"y":1214}]},{"description":"Answer","id":"64","order":"13","response":false,"vertices":[{"x":3787,"y":914}]},{"description":"StasisStart","id":"96","order":"14","response":false,"vertices":[{"x":1550,"y":164}]},{"description":"Answer call","id":"95","order":"15","response":false,"vertices":[{"x":1550,"y":764}]},{"description":"Events","id":"68","order":"16","response":false,"vertices":[{"x":855,"y":753}]}]},{"automaticLayout":{"applied":true,"edgeSeparation":0,"implementation":"Graphviz","nodeSeparation":300,"rankDirection":"LeftRight","rankSeparation":300,"vertices":false},"description":"After the bridge is up, Asterisk sends two media taps to the Ktor engine; each direction is recognized, translated, synthesized, and played to the opposite participant.","dimensions":{"height":2663,"width":2218},"elementId":"27","elements":[{"id":"4","x":1079,"y":1010},{"id":"25","x":1079,"y":1610},{"id":"26","x":1079,"y":2210},{"id":"28","x":329,"y":410},{"id":"54","x":1079,"y":410}],"externalBoundariesVisible":false,"key":"BidirectionalMediaTranslation","order":8,"relationships":[{"description":"Create caller","id":"95","order":"1","response":false},{"description":"Audio","id":"96","order":"2","response":false},{"description":"Recognize","id":"98","order":"3","response":false},{"description":"Translate","id":"100","order":"4","response":false},{"description":"Synthesize","id":"98","order":"5","response":false},{"description":"Audio","id":"95","order":"6","response":false},{"description":"Audio","id":"96","order":"7","response":false},{"description":"Recognize","id":"98","order":"8","response":false},{"description":"Translate","id":"100","order":"9","response":false},{"description":"Synthesize","id":"98","order":"10","response":false},{"description":"Audio","id":"95","order":"11","response":false},{"description":"Transcript","id":"68","order":"12","response":false}]},{"automaticLayout":{"applied":false,"edgeSeparation":0,"implementation":"Graphviz","nodeSeparation":300,"rankDirection":"LeftRight","rankSeparation":300,"vertices":false},"description":"Any hangup, channel destruction, failure, or explicit backend session deletion cleans up ARI resources and active engine state.","elementId":"27","elements":[{"id":"2","x":0,"y":0},{"id":"4","x":0,"y":0},{"id":"22","x":0,"y":0},{"id":"23","x":0,"y":0},{"id":"28","x":0,"y":0},{"id":"54","x":0,"y":0}],"externalBoundariesVisible":false,"key":"SessionCleanup","order":9,"relationships":[{"description":"Delete session","id":"66","order":"1","response":false},{"description":"Cleanup","id":"95","order":"2","response":false},{"description":"Cleanup","id":"95","order":"3","response":false},{"description":"Cleanup","id":"64","order":"4","response":false},{"description":"Release call","id":"89","order":"5","response":false},{"description":"Dial PSTN","id":"90","order":"6","response":false},{"description":"Channel left","id":"96","order":"7","response":false},{"description":"Cleanup","id":"95","order":"8","response":false},{"description":"Events","id":"68","order":"9","response":false}]},{"automaticLayout":{"applied":false,"edgeSeparation":0,"implementation":"Graphviz","nodeSeparation":300,"rankDirection":"LeftRight","rankSeparation":300,"vertices":false},"description":"Ktor call engine component interactions for SIP credential provisioning, PSTN session creation, inbound join validation, callee origination, and started callback publishing.","elementId":"28","elements":[{"id":"4","x":0,"y":0},{"id":"29","x":0,"y":0},{"id":"30","x":0,"y":0},{"id":"31","x":0,"y":0},{"id":"32","x":0,"y":0},{"id":"33","x":0,"y":0},{"id":"34","x":0,"y":0},{"id":"35","x":0,"y":0},{"id":"36","x":0,"y":0},{"id":"37","x":0,"y":0},{"id":"38","x":0,"y":0},{"id":"39","x":0,"y":0},{"id":"40","x":0,"y":0},{"id":"41","x":0,"y":0},{"id":"53","x":0,"y":0},{"id":"54","x":0,"y":0},{"id":"62","x":0,"y":0}],"externalBoundariesVisible":false,"key":"CallEngineCredentialAndPstnSessionInternals","order":10,"relationships":[{"description":"Create SIP creds","id":"102","order":"1","response":false},{"description":"JWT auth","id":"135","order":"2","response":false},{"description":"Create or fetch","id":"136","order":"3","response":false},{"description":"Dial PSTN","id":"138","order":"4","response":false},{"description":"Persist","id":"139","order":"5","response":false},{"description":"Create session","id":"102","order":"6","response":false},{"description":"Create active translator","id":"137","order":"7","response":false},{"description":"Dial PSTN","id":"140","order":"8","response":false},{"description":"Create session state","id":"141","order":"9","response":false},{"description":"Generate expiring join","id":"142","order":"10","response":false},{"description":"Return join data","id":"103","order":"11","response":false},{"description":"StasisStart","id":"176","order":"12","response":false},{"description":"Parse ARI JSON","id":"144","order":"13","response":false},{"description":"Events","id":"145","order":"14","response":false},{"description":"Validate","id":"146","order":"15","response":false},{"description":"Bind caller channel","id":"147","order":"16","response":false},{"description":"Answer caller, create","id":"148","order":"17","response":false},{"description":"ARI answer/bridge/originate commands","id":"177","order":"18","response":false},{"description":"Dial PSTN","id":"148","order":"19","response":false},{"description":"StasisStart","id":"176","order":"20","response":false},{"description":"Answer call","id":"148","order":"21","response":false},{"description":"Bridge + taps","id":"149","order":"22","response":false},{"description":"Events","id":"151","order":"23","response":false},{"description":"Events","id":"175","order":"24","response":false}]},{"automaticLayout":{"applied":false,"edgeSeparation":0,"implementation":"Graphviz","nodeSeparation":300,"rankDirection":"LeftRight","rankSeparation":300,"vertices":false},"description":"Ktor call engine component interactions for the two directional RTP translation runners.","elementId":"28","elements":[{"id":"4","x":0,"y":0},{"id":"25","x":0,"y":0},{"id":"26","x":0,"y":0},{"id":"36","x":0,"y":0},{"id":"39","x":0,"y":0},{"id":"40","x":0,"y":0},{"id":"41","x":0,"y":0},{"id":"42","x":0,"y":0},{"id":"44","x":0,"y":0},{"id":"45","x":0,"y":0},{"id":"46","x":0,"y":0},{"id":"47","x":0,"y":0},{"id":"48","x":0,"y":0},{"id":"49","x":0,"y":0},{"id":"50","x":0,"y":0},{"id":"51","x":0,"y":0},{"id":"52","x":0,"y":0},{"id":"53","x":0,"y":0},{"id":"54","x":0,"y":0}],"externalBoundariesVisible":false,"key":"CallEngineMediaTranslationInternals","order":11,"relationships":[{"description":"Bridge + taps","id":"149","order":"1","response":false},{"description":"Create caller snoop","id":"152","order":"2","response":false},{"description":"Create callee snoop","id":"152","order":"3","response":false},{"description":"Install snoop/external-media channels","id":"177","order":"4","response":false},{"description":"Store tap bridge","id":"153","order":"5","response":false},{"description":"Launch caller-to-callee","id":"154","order":"6","response":false},{"description":"Audio","id":"178","order":"7","response":false},{"description":"Audio","id":"163","order":"8","response":false},{"description":"Recognize","id":"165","order":"9","response":false},{"description":"Audio","id":"172","order":"10","response":false},{"description":"Translate","id":"166","order":"11","response":false},{"description":"Request translation","id":"173","order":"12","response":false},{"description":"Synthesize","id":"167","order":"13","response":false},{"description":"Synthesize","id":"174","order":"14","response":false},{"description":"Register callee playback","id":"169","order":"15","response":false},{"description":"Audio","id":"170","order":"16","response":false},{"description":"Persist","id":"171","order":"17","response":false},{"description":"Audio","id":"178","order":"18","response":false},{"description":"Audio","id":"164","order":"19","response":false},{"description":"Recognize","id":"165","order":"20","response":false},{"description":"Translate","id":"166","order":"21","response":false},{"description":"Synthesize","id":"167","order":"22","response":false},{"description":"Register caller playback","id":"169","order":"23","response":false},{"description":"Audio","id":"170","order":"24","response":false},{"description":"Transcript","id":"168","order":"25","response":false},{"description":"Events","id":"175","order":"26","response":false}]},{"automaticLayout":{"applied":false,"edgeSeparation":0,"implementation":"Graphviz","nodeSeparation":300,"rankDirection":"LeftRight","rankSeparation":300,"vertices":false},"description":"Ktor call engine component interactions for hangup, failure, and explicit backend session deletion cleanup.","elementId":"28","elements":[{"id":"4","x":0,"y":0},{"id":"29","x":0,"y":0},{"id":"33","x":0,"y":0},{"id":"36","x":0,"y":0},{"id":"37","x":0,"y":0},{"id":"38","x":0,"y":0},{"id":"39","x":0,"y":0},{"id":"40","x":0,"y":0},{"id":"42","x":0,"y":0},{"id":"43","x":0,"y":0},{"id":"53","x":0,"y":0},{"id":"54","x":0,"y":0}],"externalBoundariesVisible":false,"key":"CallEngineCleanupInternals","order":12,"relationships":[{"description":"Delete session","id":"102","order":"1","response":false},{"description":"Delete active session","id":"137","order":"2","response":false},{"description":"Transition session","id":"141","order":"3","response":false},{"description":"End session","id":"143","order":"4","response":false},{"description":"Channel left","id":"176","order":"5","response":false},{"description":"Events","id":"144","order":"6","response":false},{"description":"Events","id":"145","order":"7","response":false},{"description":"Validate","id":"147","order":"8","response":false},{"description":"Cleanup","id":"150","order":"9","response":false},{"description":"Cleanup","id":"157","order":"10","response":false},{"description":"Cleanup","id":"157","order":"11","response":false},{"description":"Stop conversation runners","id":"158","order":"12","response":false},{"description":"Remove session indexes","id":"159","order":"13","response":false},{"description":"Events","id":"160","order":"14","response":false},{"description":"Events","id":"175","order":"15","response":false}]},{"automaticLayout":{"applied":false,"edgeSeparation":0,"implementation":"Graphviz","nodeSeparation":300,"rankDirection":"LeftRight","rankSeparation":300,"vertices":false},"description":"Rails account creation requests generated SIP credentials from the Ktor call engine and stores them with the caller account.","elementId":"5","elements":[{"id":"3","x":0,"y":0},{"id":"6","x":0,"y":0},{"id":"7","x":0,"y":0},{"id":"11","x":0,"y":0},{"id":"14","x":0,"y":0},{"id":"15","x":0,"y":0},{"id":"18","x":0,"y":0},{"id":"19","x":0,"y":0},{"id":"24","x":0,"y":0},{"id":"28","x":0,"y":0}],"externalBoundariesVisible":false,"key":"BusinessBackendAccountProvisioning","order":13,"relationships":[{"description":"Create account","id":"111","order":"1","response":false},{"description":"JWT auth","id":"104","order":"2","response":false},{"description":"Create or update account","id":"107","order":"3","response":false},{"description":"Create SIP credentials","id":"117","order":"4","response":false},{"description":"Create SIP creds","id":"118","order":"5","response":false},{"description":"Return join data","id":"120","order":"6","response":false},{"description":"Persist","id":"122","order":"7","response":false},{"description":"Persist","id":"132","order":"8","response":false},{"description":"Send confirmation code","id":"123","order":"9","response":false},{"description":"POST SMS request","id":"124","order":"10","response":false},{"description":"Return account creation","id":"114","order":"11","response":false}]},{"automaticLayout":{"applied":false,"edgeSeparation":0,"implementation":"Graphviz","nodeSeparation":300,"rankDirection":"LeftRight","rankSeparation":300,"vertices":false},"description":"Rails validates a client call request, asks the Ktor call engine for a session, persists the call, and returns SIP join details to the VoIP client.","elementId":"5","elements":[{"id":"3","x":0,"y":0},{"id":"6","x":0,"y":0},{"id":"9","x":0,"y":0},{"id":"12","x":0,"y":0},{"id":"14","x":0,"y":0},{"id":"15","x":0,"y":0},{"id":"19","x":0,"y":0},{"id":"28","x":0,"y":0}],"externalBoundariesVisible":false,"key":"BusinessBackendCallInitialization","order":14,"relationships":[{"description":"Init call","id":"113","order":"1","response":false},{"description":"JWT auth","id":"106","order":"2","response":false},{"description":"Initialize translated call","id":"109","order":"3","response":false},{"description":"Validate","id":"125","order":"4","response":false},{"description":"Read identities_accounts, calls","id":"132","order":"5","response":false},{"description":"Create call-engine session","id":"126","order":"6","response":false},{"description":"Create session","id":"118","order":"7","response":false},{"description":"Return join data","id":"120","order":"8","response":false},{"description":"Return join data","id":"125","order":"9","response":false},{"description":"Persist","id":"132","order":"10","response":false},{"description":"Return join data","id":"116","order":"11","response":false}]},{"automaticLayout":{"applied":false,"edgeSeparation":0,"implementation":"Graphviz","nodeSeparation":300,"rankDirection":"LeftRight","rankSeparation":300,"vertices":false},"description":"Rails handles call-engine callbacks, updates call state, persists transcripts, adjusts remaining time, and pushes notifications to the client.","elementId":"5","elements":[{"id":"3","x":0,"y":0},{"id":"10","x":0,"y":0},{"id":"13","x":0,"y":0},{"id":"15","x":0,"y":0},{"id":"16","x":0,"y":0},{"id":"17","x":0,"y":0},{"id":"19","x":0,"y":0},{"id":"20","x":0,"y":0},{"id":"28","x":0,"y":0}],"externalBoundariesVisible":false,"key":"BusinessBackendCallEventHandling","order":15,"relationships":[{"description":"Post event","id":"133","order":"1","response":false},{"description":"Validate","id":"110","order":"2","response":false},{"description":"Transcript","id":"127","order":"3","response":false},{"description":"Persist","id":"132","order":"4","response":false},{"description":"Transcript","id":"128","order":"5","response":false},{"description":"Notify","id":"129","order":"6","response":false},{"description":"Publish ActionCable message","id":"130","order":"7","response":false},{"description":"Notify","id":"131","order":"8","response":false}]}],"systemContextViews":[{"automaticLayout":{"applied":false,"edgeSeparation":0,"implementation":"Graphviz","nodeSeparation":300,"rankDirection":"LeftRight","rankSeparation":300,"vertices":false},"description":"External people and systems involved in a translated PSTN call.","elements":[{"id":"3","x":0,"y":0},{"id":"4","x":0,"y":0},{"id":"22","x":0,"y":0},{"id":"25","x":0,"y":0},{"id":"26","x":0,"y":0},{"id":"27","x":0,"y":0}],"enterpriseBoundaryVisible":true,"key":"SystemContext","order":1,"relationships":[{"id":"101"},{"id":"65"},{"id":"67"},{"id":"69"},{"id":"70"},{"id":"84"},{"id":"87"},{"id":"91"},{"id":"99"}],"softwareSystemId":"27"}]}}