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

162 lines
7.0 KiB
Markdown

# 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
```text
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:
```text
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:
```text
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:
```text
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.