From 92792cdc5007168349397c063706e0c61573f1be Mon Sep 17 00:00:00 2001 From: "Andrew M. Stoltz" <1578013+astoltz@users.noreply.github.com> Date: Fri, 20 Mar 2026 10:51:28 -0500 Subject: [PATCH] Route inbound PSTN calls through FlowerCore IVR, add missing star codes from-twilio: Changed from Dial(PJSIP/100) to Stasis(flowercore-pbx,inbound-pstn) so inbound calls go through the FlowerCore IVR workflow engine instead of directly ringing extensions. Added missing star codes: *43 (echo test), *80 (intercom), *88 (conference), *41/*411 (directory). Added catch-all _*X. pattern for future star codes. Co-Authored-By: Claude Opus 4.6 (1M context) --- apps/asterisk/configmap.yaml | 529 ++++++++++++++++++----------------- 1 file changed, 269 insertions(+), 260 deletions(-) diff --git a/apps/asterisk/configmap.yaml b/apps/asterisk/configmap.yaml index 218b67b..59533d5 100644 --- a/apps/asterisk/configmap.yaml +++ b/apps/asterisk/configmap.yaml @@ -1,260 +1,269 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: asterisk-config - namespace: telephony -data: - modules.conf: | - [modules] - autoload=yes - noload=chan_sip.so - noload=res_hep.so - noload=res_hep_pjsip.so - noload=res_hep_rtcp.so - - http.conf: | - [general] - enabled=yes - bindaddr=0.0.0.0 - bindport=8088 - - ari.conf: | - [general] - enabled=yes - pretty=yes - allowed_origins=* - - [flowercore] - type=user - read_only=no - password=bluejay-asterisk-ari - password_format=plain - - manager.conf: | - [general] - enabled=no - - pjsip.conf: | - ; ===== Transports ===== - [transport-udp] - type=transport - protocol=udp - bind=0.0.0.0:5060 - ; NAT: internal phones see node IP, Twilio sees public IP - local_net=10.0.0.0/8 - local_net=172.16.0.0/12 - local_net=192.168.0.0/16 - external_media_address=74.40.140.28 - external_signaling_address=74.40.140.28 - - ; ===== Twilio SIP Trunk ===== - [twilio-trunk] - type=endpoint - context=from-twilio - transport=transport-udp - disallow=all - allow=ulaw - allow=alaw - allow=g722 - aors=twilio-trunk - from_domain=sip.twilio.com - direct_media=no - ice_support=no - rtp_symmetric=yes - force_rport=yes - rewrite_contact=yes - trust_id_inbound=yes - - [twilio-trunk] - type=aor - contact=sip:bluejay.pstn.twilio.com - - [twilio-trunk] - type=identify - endpoint=twilio-trunk - ; Twilio North America signaling IPs - match=54.172.60.0/30 - match=54.172.60.4/30 - match=54.244.51.0/30 - match=54.244.51.4/30 - match=34.203.250.0/23 - match=54.171.127.192/26 - match=35.156.191.128/25 - match=54.65.63.192/26 - match=54.169.127.128/26 - match=54.252.254.64/26 - match=177.71.206.192/26 - - ; ===== Yealink Phone Template ===== - [phone-template](!) - type=endpoint - context=from-internal - transport=transport-udp - disallow=all - allow=opus - allow=g722 - allow=ulaw - allow=alaw - direct_media=no - dtmf_mode=rfc4733 - rtp_symmetric=yes - force_rport=yes - rewrite_contact=yes - - ; Extension 100 - Reception - [100](phone-template) - auth=auth100 - aors=100 - callerid="Reception" <100> - - [auth100] - type=auth - auth_type=userpass - username=100 - password=bluejay-ext-100 - - [100] - type=aor - max_contacts=1 - remove_existing=yes - qualify_frequency=60 - - ; Extension 101 - Office 1 - [101](phone-template) - auth=auth101 - aors=101 - callerid="Office 1" <101> - - [auth101] - type=auth - auth_type=userpass - username=101 - password=bluejay-ext-101 - - [101] - type=aor - max_contacts=1 - remove_existing=yes - qualify_frequency=60 - - ; Extension 102 - Office 2 - [102](phone-template) - auth=auth102 - aors=102 - callerid="Office 2" <102> - - [auth102] - type=auth - auth_type=userpass - username=102 - password=bluejay-ext-102 - - [102] - type=aor - max_contacts=1 - remove_existing=yes - qualify_frequency=60 - - ; Extension 103 - Office 3 - [103](phone-template) - auth=auth103 - aors=103 - callerid="Office 3" <103> - - [auth103] - type=auth - auth_type=userpass - username=103 - password=bluejay-ext-103 - - [103] - type=aor - max_contacts=1 - remove_existing=yes - qualify_frequency=60 - - extensions.conf: | - [general] - static=yes - writeprotect=no - - [from-twilio] - ; Inbound calls from Twilio SIP trunk - ; Ring reception (100) for 30s, then try all extensions in ring group - exten => _+X.,1,Answer() - same => n,Playback(silence/1) - same => n,Dial(PJSIP/100,30,t) - same => n,Dial(PJSIP/101&PJSIP/102&PJSIP/103,30,t) - same => n,Playback(vm-goodbye) - same => n,Hangup() - - exten => _X.,1,Answer() - same => n,Playback(silence/1) - same => n,Dial(PJSIP/100,30,t) - same => n,Dial(PJSIP/101&PJSIP/102&PJSIP/103,30,t) - same => n,Playback(vm-goodbye) - same => n,Hangup() - - [from-internal] - ; Internal extension-to-extension dialing - exten => _1XX,1,Dial(PJSIP/${EXTEN},30) - same => n,Hangup() - - ; Outbound via Twilio SIP trunk (11-digit US) - exten => _1NXXNXXXXXX,1,Set(CALLERID(num)=+13202332529) - same => n,Dial(PJSIP/+${EXTEN}@twilio-trunk,60) - same => n,Hangup() - - ; Outbound via Twilio SIP trunk (+1 format) - exten => _+1NXXNXXXXXX,1,Set(CALLERID(num)=+13202332529) - same => n,Dial(PJSIP/${EXTEN}@twilio-trunk,60) - same => n,Hangup() - - ; IVR access from internal phones (when ARI is connected) - exten => *100,1,Stasis(flowercore-pbx,internal,ivr) - same => n,Hangup() - - ; Star codes routed to FlowerCore Stasis app for handling - exten => *0,1,Stasis(flowercore-pbx,starcode,*0) - same => n,Hangup() - exten => *30,1,Stasis(flowercore-pbx,starcode,*30) - same => n,Hangup() - exten => *69,1,Stasis(flowercore-pbx,starcode,*69) - same => n,Hangup() - exten => *70,1,Stasis(flowercore-pbx,starcode,*70) - same => n,Hangup() - exten => _*70X.,1,Stasis(flowercore-pbx,starcode,${EXTEN}) - same => n,Hangup() - exten => *71,1,Stasis(flowercore-pbx,starcode,*71) - same => n,Hangup() - exten => _*71X.,1,Stasis(flowercore-pbx,starcode,${EXTEN}) - same => n,Hangup() - exten => *72,1,Stasis(flowercore-pbx,starcode,*72) - same => n,Hangup() - exten => *73,1,Stasis(flowercore-pbx,starcode,*73) - same => n,Hangup() - exten => *75,1,Stasis(flowercore-pbx,starcode,*75) - same => n,Hangup() - exten => *77,1,Stasis(flowercore-pbx,starcode,*77) - same => n,Hangup() - exten => *78,1,Stasis(flowercore-pbx,starcode,*78) - same => n,Hangup() - exten => *79,1,Stasis(flowercore-pbx,starcode,*79) - same => n,Hangup() - exten => *86,1,Stasis(flowercore-pbx,starcode,*86) - same => n,Hangup() - exten => *87,1,Stasis(flowercore-pbx,starcode,*87) - same => n,Hangup() - exten => *97,1,Stasis(flowercore-pbx,starcode,*97) - same => n,Hangup() - - [default] - exten => _X.,1,NoOp(Unhandled call to ${EXTEN}) - same => n,Hangup() - - rtp.conf: | - [general] - rtpstart=10000 - rtpend=20000 - strictrtp=yes - icesupport=no +apiVersion: v1 +kind: ConfigMap +metadata: + name: asterisk-config + namespace: telephony +data: + modules.conf: | + [modules] + autoload=yes + noload=chan_sip.so + noload=res_hep.so + noload=res_hep_pjsip.so + noload=res_hep_rtcp.so + + http.conf: | + [general] + enabled=yes + bindaddr=0.0.0.0 + bindport=8088 + + ari.conf: | + [general] + enabled=yes + pretty=yes + allowed_origins=* + + [flowercore] + type=user + read_only=no + password=bluejay-asterisk-ari + password_format=plain + + manager.conf: | + [general] + enabled=no + + pjsip.conf: | + ; ===== Transports ===== + [transport-udp] + type=transport + protocol=udp + bind=0.0.0.0:5060 + ; NAT: internal phones see node IP, Twilio sees public IP + local_net=10.0.0.0/8 + local_net=172.16.0.0/12 + local_net=192.168.0.0/16 + external_media_address=74.40.140.28 + external_signaling_address=74.40.140.28 + + ; ===== Twilio SIP Trunk ===== + [twilio-trunk] + type=endpoint + context=from-twilio + transport=transport-udp + disallow=all + allow=ulaw + allow=alaw + allow=g722 + aors=twilio-trunk + from_domain=sip.twilio.com + direct_media=no + ice_support=no + rtp_symmetric=yes + force_rport=yes + rewrite_contact=yes + trust_id_inbound=yes + + [twilio-trunk] + type=aor + contact=sip:bluejay.pstn.twilio.com + + [twilio-trunk] + type=identify + endpoint=twilio-trunk + ; Twilio North America signaling IPs + match=54.172.60.0/30 + match=54.172.60.4/30 + match=54.244.51.0/30 + match=54.244.51.4/30 + match=34.203.250.0/23 + match=54.171.127.192/26 + match=35.156.191.128/25 + match=54.65.63.192/26 + match=54.169.127.128/26 + match=54.252.254.64/26 + match=177.71.206.192/26 + + ; ===== Yealink Phone Template ===== + [phone-template](!) + type=endpoint + context=from-internal + transport=transport-udp + disallow=all + allow=opus + allow=g722 + allow=ulaw + allow=alaw + direct_media=no + dtmf_mode=rfc4733 + rtp_symmetric=yes + force_rport=yes + rewrite_contact=yes + + ; Extension 100 - Reception + [100](phone-template) + auth=auth100 + aors=100 + callerid="Reception" <100> + + [auth100] + type=auth + auth_type=userpass + username=100 + password=bluejay-ext-100 + + [100] + type=aor + max_contacts=1 + remove_existing=yes + qualify_frequency=60 + + ; Extension 101 - Office 1 + [101](phone-template) + auth=auth101 + aors=101 + callerid="Office 1" <101> + + [auth101] + type=auth + auth_type=userpass + username=101 + password=bluejay-ext-101 + + [101] + type=aor + max_contacts=1 + remove_existing=yes + qualify_frequency=60 + + ; Extension 102 - Office 2 + [102](phone-template) + auth=auth102 + aors=102 + callerid="Office 2" <102> + + [auth102] + type=auth + auth_type=userpass + username=102 + password=bluejay-ext-102 + + [102] + type=aor + max_contacts=1 + remove_existing=yes + qualify_frequency=60 + + ; Extension 103 - Office 3 + [103](phone-template) + auth=auth103 + aors=103 + callerid="Office 3" <103> + + [auth103] + type=auth + auth_type=userpass + username=103 + password=bluejay-ext-103 + + [103] + type=aor + max_contacts=1 + remove_existing=yes + qualify_frequency=60 + + extensions.conf: | + [general] + static=yes + writeprotect=no + + [from-twilio] + ; Inbound calls from Twilio SIP trunk -> FlowerCore IVR workflow + exten => _+X.,1,Answer() + same => n,Wait(1) + same => n,Stasis(flowercore-pbx,inbound-pstn,${EXTEN}) + same => n,Hangup() + + exten => _X.,1,Answer() + same => n,Wait(1) + same => n,Stasis(flowercore-pbx,inbound-pstn,${EXTEN}) + same => n,Hangup() + + [from-internal] + ; Internal extension-to-extension dialing + exten => _1XX,1,Dial(PJSIP/${EXTEN},30) + same => n,Hangup() + + ; Outbound via Twilio SIP trunk (11-digit US) + exten => _1NXXNXXXXXX,1,Set(CALLERID(num)=+13202332529) + same => n,Dial(PJSIP/+${EXTEN}@twilio-trunk,60) + same => n,Hangup() + + ; Outbound via Twilio SIP trunk (+1 format) + exten => _+1NXXNXXXXXX,1,Set(CALLERID(num)=+13202332529) + same => n,Dial(PJSIP/${EXTEN}@twilio-trunk,60) + same => n,Hangup() + + ; IVR access from internal phones (when ARI is connected) + exten => *100,1,Stasis(flowercore-pbx,internal,ivr) + same => n,Hangup() + + ; Star codes routed to FlowerCore Stasis app for handling + exten => *0,1,Stasis(flowercore-pbx,starcode,*0) + same => n,Hangup() + exten => *30,1,Stasis(flowercore-pbx,starcode,*30) + same => n,Hangup() + exten => *69,1,Stasis(flowercore-pbx,starcode,*69) + same => n,Hangup() + exten => *70,1,Stasis(flowercore-pbx,starcode,*70) + same => n,Hangup() + exten => _*70X.,1,Stasis(flowercore-pbx,starcode,${EXTEN}) + same => n,Hangup() + exten => *71,1,Stasis(flowercore-pbx,starcode,*71) + same => n,Hangup() + exten => _*71X.,1,Stasis(flowercore-pbx,starcode,${EXTEN}) + same => n,Hangup() + exten => *72,1,Stasis(flowercore-pbx,starcode,*72) + same => n,Hangup() + exten => *73,1,Stasis(flowercore-pbx,starcode,*73) + same => n,Hangup() + exten => *75,1,Stasis(flowercore-pbx,starcode,*75) + same => n,Hangup() + exten => *77,1,Stasis(flowercore-pbx,starcode,*77) + same => n,Hangup() + exten => *78,1,Stasis(flowercore-pbx,starcode,*78) + same => n,Hangup() + exten => *79,1,Stasis(flowercore-pbx,starcode,*79) + same => n,Hangup() + exten => *86,1,Stasis(flowercore-pbx,starcode,*86) + same => n,Hangup() + exten => *87,1,Stasis(flowercore-pbx,starcode,*87) + same => n,Hangup() + exten => *97,1,Stasis(flowercore-pbx,starcode,*97) + same => n,Hangup() + exten => *43,1,Stasis(flowercore-pbx,starcode,*43) + same => n,Hangup() + exten => *80,1,Stasis(flowercore-pbx,starcode,*80) + same => n,Hangup() + exten => *88,1,Stasis(flowercore-pbx,starcode,*88) + same => n,Hangup() + exten => *41,1,Stasis(flowercore-pbx,starcode,*41) + same => n,Hangup() + exten => *411,1,Stasis(flowercore-pbx,starcode,*411) + same => n,Hangup() + + ; Catch-all for any other star codes + exten => _*X.,1,Stasis(flowercore-pbx,starcode,${EXTEN}) + same => n,Hangup() + + [default] + exten => _X.,1,NoOp(Unhandled call to ${EXTEN}) + same => n,Hangup() + + rtp.conf: | + [general] + rtpstart=10000 + rtpend=20000 + strictrtp=yes + icesupport=no