Files
go-sip/docs/evidence/20260918-w09-ari-runtime.md
T

7.0 KiB

W09 isolated Asterisk/ARI runtime PoC (2026-09-18)

Scope and boundary

This is an owner-authorized, mock-only compatibility probe on the existing Debian 13 ECS test host. It does not use a SIP provider, a real phone number, SaaS, RabbitMQ, OSS, AI credentials, or the production Agent binary. It is not W09, W13, W14, or P1 acceptance.

The probe was deliberately kept outside the project module at /tmp/ari-poc. It uses the already reviewed temporary module:

  • github.com/CyCoreSystems/ari/v5 v5.3.1
  • module checksum: h1:S+NHG1+uMwoAIl0hMBnRUGNZsQKQQQFq7XCRSE2c2mg=
  • Asterisk runtime: 22.10.1
  • source image reference: andrius/asterisk@sha256:1fde2a38e17c42c4f8999bb80d2ac52a01543bc696a98e02faee1cf6f14d4d64
  • transferred image ID on the host: sha256:08c732ed191c02ad54c019c4e6b46b641bb3ebbe42fcd5b525eb41c6373f6128

The image was transferred as an archive because Docker Hub was unreachable from the host. The host-local tag is only a transport/runtime tag; it is not a new upstream digest claim. The container is on the isolated Docker network agent-call-asterisk-poc, with ARI published only on host loopback 127.0.0.1:18088.

Runtime procedure

The temporary Go probe:

  1. listened on host UDP 0.0.0.0:19000 as the external-media sink;
  2. connected to ARI with the mock sipmock application and mock credentials;
  3. originated an internal Local/900001@ari-gate channel, with no provider leg;
  4. waited for StasisStart;
  5. created a mixing bridge and added the internal channel;
  6. created an ExternalMedia channel using RTP/UDP, PCMA (alaw), direction both, and external host 172.18.0.1:19000;
  7. waited for the ExternalMedia StasisStart, added it to the bridge, read UNICASTRTP_LOCAL_ADDRESS and UNICASTRTP_LOCAL_PORT, and then hung it up;
  8. observed StasisEnd for the ExternalMedia channel.

The build and execution used the host-installed Go toolchain with GOTOOLCHAIN=local; the resulting probe binary was copied to the ECS host and run as rogee.

Observed output

local_channel=ari-poc-local
stasis_start channel=ari-poc-local args=[]
bridge=ari-poc-bridge data=&{Key:ari-poc-bridge ID:ari-poc-bridge Class:stasis Type:mixing ChannelIDs:[01m2syek1a93x6jkz567r1m3j8-ch ari-poc-local] Creator:Stasis Name:ari-poc-bridge Technology:simple_bridge}
external_channel=01m2syek1a93x6jkz567r1m3j8-ch state=Up name=UnicastRTP/172.18.0.1:19000-0x7f51780063b0
local_rtp=172.18.0.2:10748
probe_packets=0 peer=<nil> read_error=read udp4 0.0.0.0:19000: i/o timeout
stasis_end channel=01m2syek1a93x6jkz567r1m3j8-ch

The first run exposed a real ordering requirement: adding ExternalMedia to the bridge before its StasisStart was observable returned HTTP 422. Waiting for that event made the bridge add succeed. This is useful compatibility evidence, not a production implementation.

Controlled RTP forwarding follow-up

A second temporary probe used two independent ExternalMedia channels in the same mixing bridge. Both were configured as RTP/UDP, PCMA (alaw), direction both. The host listened on 172.18.0.1:19000 and 172.18.0.1:19001, sent 20 synthetic RTP packets to the first channel's Asterisk-local port, and captured the bridge output at the second host port.

The successful run, after restarting only the isolated PoC container to clear connections left by a timed-out disposable probe, returned:

connected
bridge_created
first_created=01m2szdw9r2s4erk251qpm4pme-ch
first_stasis
first_added
second_created=01m2szdwa1p6a16jtqsyphcefj-ch
second_stasis
second_added
bridge=ari-poc-media first=172.18.0.2:10724 second=172.18.0.2:10256
forwarded_rtp_bytes=172 peer=172.18.0.2:10256 version=2 payload_type=8 sequence=63988 timestamp=800 ssrc=1b5ec593
stasis_end channel=01m2szdwa1p6a16jtqsyphcefj-ch
stasis_end channel=01m2szdw9r2s4erk251qpm4pme-ch
remote_rc=0
channels: []
bridges: []

This proves a controlled host-to-Asterisk-to-host RTP path through an Asterisk mixing bridge and confirms RTP version 2, PCMA payload type 8, and lifecycle cleanup. Asterisk rewrote the forwarded sequence/timestamp/SSRC; payload identity and production jitter/clock behavior were not assessed.

Recording close follow-up

A third temporary probe created the same two-channel synthetic bridge, started an ARI bridge recording with format wav, injected 40 PCMA packets, stopped the recording explicitly, and read the stored-recording metadata. The isolated container first received the missing /var/spool/asterisk/recording directory with asterisk:asterisk ownership; this was a disposable mock-container setup change, not a production artifact.

The run returned:

connected
recording_started name=ari-poc-record-20260918 format=wav state=recording
forwarded_rtp_bytes=172 peer=172.18.0.2:10250 payload_type=8
recording_stopped name=ari-poc-record-20260918 format=wav
stasis_end channel=01m2szqryme5sm3w89866j2key-ch
stasis_end channel=01m2szqryxqpz6xgakr28bgdj0-ch
recording_name=ari-poc-record-20260918

The closed file was inspected before cleanup:

size=13804 mode=644 owner=asterisk:asterisk path=/var/spool/asterisk/recording/ari-poc-record-20260918.wav
sha256=c62bede7c200c99a9fb9d73eee11ebefe71397b71aeff4dbfe0a05dc7d112e82
header=RIFF/WAVE, PCM mono, 8000 Hz, 16-bit
channels: []
bridges: []
recording_cleanup=ok

The synthetic recording file was then removed from the disposable container. This proves ARI recording start/stop, a closed WAV header, and cleanup in the isolated environment; it does not prove business recording retention or OSS upload semantics.

Result

Passed in isolation: Asterisk 22.10.1 accepted the selected ARI client at runtime; internal Stasis channels and mixing bridges were created; RTP/UDP PCMA ExternalMedia channels reached Up; Asterisk-local RTP addresses and ports were retrievable; bridge insertion required and honored StasisStart; a controlled RTP packet stream traversed the bridge; an ARI bridge recording started and stopped with a valid closed WAV file; the artifact was cleaned; and both channels produced clean StasisEnd lifecycle events.

Not proven: this remains synthetic ExternalMedia-to-ExternalMedia traffic, not a SIP/RTP provider leg or an Agent media session. The separate isolated SIPp-to-PJSIP/ARI signaling result is recorded in docs/evidence/20260918-w09-sip-ari.md. Full same-channel bidirectional semantics, exact PCMA sample preservation, reconnect/fencing behavior, provider lines, static artifact loading, Agent integration, retention/OSS upload, and capacity were not tested. The result therefore only advances the compatibility PoC and does not unlock W09's full M/G gate or any P1/production claim.

Follow-up gate

Before selecting ARI in the production module, retain this runtime result and complete the separate library/license/security review, full media-session and reconnect/fencing tests, approved static Asterisk/Cell artifact loading, retention/OSS handoff, and the remaining SIP/provider validation. Real provider and telephone tests remain under W14 authorization and are not implied by this document.