Update telephony-web image tag to v20260324d (Scalar API docs, webhook config, surveys, templates, member portal)
This commit is contained in:
@@ -1,349 +1,349 @@
|
|||||||
# FlowerCore.Telephony - Blazor Server + REST API + Twilio IVR
|
# FlowerCore.Telephony - Blazor Server + REST API + Twilio IVR
|
||||||
# ArgoCD managed - BlueJay Lab
|
# ArgoCD managed - BlueJay Lab
|
||||||
# Credentials: 1Password → OnePasswordItem CRD → K8s Secret (twilio-credentials)
|
# Credentials: 1Password → OnePasswordItem CRD → K8s Secret (twilio-credentials)
|
||||||
# TTS: Piper on edge1 (10.0.57.15:8500)
|
# TTS: Piper on edge1 (10.0.57.15:8500)
|
||||||
# Public: telephony.flowercore.io via Cloudflare origin cert
|
# Public: telephony.flowercore.io via Cloudflare origin cert
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Namespace
|
kind: Namespace
|
||||||
metadata:
|
metadata:
|
||||||
name: telephony
|
name: telephony
|
||||||
labels:
|
labels:
|
||||||
app.kubernetes.io/part-of: bluejay-infra
|
app.kubernetes.io/part-of: bluejay-infra
|
||||||
---
|
---
|
||||||
# Cloudflare Origin Certificate for *.flowercore.io + *.iamwork.in (15-year RSA)
|
# Cloudflare Origin Certificate for *.flowercore.io + *.iamwork.in (15-year RSA)
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Secret
|
kind: Secret
|
||||||
metadata:
|
metadata:
|
||||||
name: cf-origin-flowercore-io
|
name: cf-origin-flowercore-io
|
||||||
namespace: telephony
|
namespace: telephony
|
||||||
type: kubernetes.io/tls
|
type: kubernetes.io/tls
|
||||||
data:
|
data:
|
||||||
tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVvRENDQTRpZ0F3SUJBZ0lVSXN4c1NKV1VRL0tqZ09ldk81YnNuVi9rZVE4d0RRWUpLb1pJaHZjTkFRRUwKQlFBd2dZc3hDekFKQmdOVkJBWVRBbFZUTVJrd0Z3WURWUVFLRXhCRGJHOTFaRVpzWVhKbExDQkpibU11TVRRdwpNZ1lEVlFRTEV5dERiRzkxWkVac1lYSmxJRTl5YVdkcGJpQlRVMHdnUTJWeWRHbG1hV05oZEdVZ1FYVjBhRzl5CmFYUjVNUll3RkFZRFZRUUhFdzFUWVc0Z1JuSmhibU5wYzJOdk1STXdFUVlEVlFRSUV3cERZV3hwWm05eWJtbGgKTUI0WERUSTJNRE14TURFMk16TXdNRm9YRFRReE1ETXdOakUyTXpNd01Gb3dZakVaTUJjR0ExVUVDaE1RUTJ4dgpkV1JHYkdGeVpTd2dTVzVqTGpFZE1Cc0dBMVVFQ3hNVVEyeHZkV1JHYkdGeVpTQlBjbWxuYVc0Z1EwRXhKakFrCkJnTlZCQU1USFVOc2IzVmtSbXhoY21VZ1QzSnBaMmx1SUVObGNuUnBabWxqWVhSbE1JSUJJakFOQmdrcWhraUcKOXcwQkFRRUZBQU9DQVE0QU1JSUJDZ0tDQVFFQXV0QmpkQ0xEdHdMQlZCU0Y1ZU1OMkt3ckIxTmZmRVhRMjlRRAo1aVR0dzJFcEZXNVJJSllkMjNrYUpCMU5jZXpHWlg4a0Q0cGEyWHpFZW1MVEtJNWw0MU11b3FoWjczNVE3U3RWCkVjRFFTT2ZYTkZQdFMwb0hqb0pRdGF2QjM0ZmJNR3l4Mmx0MU9HUzRNMGtLUWpBNWR6OTJQYjNyZ1RKR0JhOW4KeTZtVThncjRuUHRSdklxZ3NxdjRtMFA3dVU1YjE3NzU1Y2JLSDVoMzIxWHVjMDU4Tzl4M2JHQ0NuRUJXWDdqeApjRGhkUEs1Ri9XRjVBQnl5cFhIQ0ZxUUd4M1NVbmtCQ0ZQSmRabnMra3BHVUZWZGhud3B6NjBtNnlJSzQ0eVR4CjZqR3JOTFEyM1dOK2gwU1lCZU5vb2JBWThydkpiVlZEaGJqSVhBTWtFNGQzVll1TlhRSURBUUFCbzRJQklqQ0MKQVI0d0RnWURWUjBQQVFIL0JBUURBZ1dnTUIwR0ExVWRKUVFXTUJRR0NDc0dBUVVGQndNQ0JnZ3JCZ0VGQlFjRApBVEFNQmdOVkhSTUJBZjhFQWpBQU1CMEdBMVVkRGdRV0JCUkt1NkJVUDZ0N2dpbFRPay9FdEdKQ3R6N3dTREFmCkJnTlZIU01FR0RBV2dCUWs2Rk5YWFh3MFFJZXA2NVRidXVFV2VQd3BwREJBQmdnckJnRUZCUWNCQVFRME1ESXcKTUFZSUt3WUJCUVVITUFHR0pHaDBkSEE2THk5dlkzTndMbU5zYjNWa1pteGhjbVV1WTI5dEwyOXlhV2RwYmw5agpZVEFqQmdOVkhSRUVIREFhZ2d3cUxtbGhiWGR2Y21zdWFXNkNDbWxoYlhkdmNtc3VhVzR3T0FZRFZSMGZCREV3Ckx6QXRvQ3VnS1lZbmFIUjBjRG92TDJOeWJDNWpiRzkxWkdac1lYSmxMbU52YlM5dmNtbG5hVzVmWTJFdVkzSnMKTUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFDSjMvTGNleE5pb0lWdUxoemhmbTZCeDV2SWk3T25CaHF1WUlDdwplNnArZ0prdE16ZFJQcDV0bk03dllBWmxMajVJOTByWDRuczhJc3dEbzJBN2wwYTRGZVJFclFmRklsZXQzbjIyCjUxVTZYVElCSks5c1FZT0FkU3pJUzV1OUNKSFpBUTF5WmxSd3BBR3RVWnhxL1dpcGFWUTRwNXhrcEJNMVlZSlAKNW1jQ09HcFErSnpORlpQc2daYUJncDBYL1BBZkNJRkkyZld5QWE2elBqRm0rdDVXUXIrZlBaT2VUS2VIbWVzVgo3UlZxUUdEb3Q0eTY1NklEdmdmU2ZLRnFIRW9XNDJVbDBxQ05hMS9keEJld3NIS1VWWE1ETkdiQlNVQjM4TG9YCm1OQ3hJQlVOUjR0TG1CQUxZT3hVMnZhSWRCd0xBc2YrcndnVnVjUGpCUTc2VWMwUQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
|
tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVvRENDQTRpZ0F3SUJBZ0lVSXN4c1NKV1VRL0tqZ09ldk81YnNuVi9rZVE4d0RRWUpLb1pJaHZjTkFRRUwKQlFBd2dZc3hDekFKQmdOVkJBWVRBbFZUTVJrd0Z3WURWUVFLRXhCRGJHOTFaRVpzWVhKbExDQkpibU11TVRRdwpNZ1lEVlFRTEV5dERiRzkxWkVac1lYSmxJRTl5YVdkcGJpQlRVMHdnUTJWeWRHbG1hV05oZEdVZ1FYVjBhRzl5CmFYUjVNUll3RkFZRFZRUUhFdzFUWVc0Z1JuSmhibU5wYzJOdk1STXdFUVlEVlFRSUV3cERZV3hwWm05eWJtbGgKTUI0WERUSTJNRE14TURFMk16TXdNRm9YRFRReE1ETXdOakUyTXpNd01Gb3dZakVaTUJjR0ExVUVDaE1RUTJ4dgpkV1JHYkdGeVpTd2dTVzVqTGpFZE1Cc0dBMVVFQ3hNVVEyeHZkV1JHYkdGeVpTQlBjbWxuYVc0Z1EwRXhKakFrCkJnTlZCQU1USFVOc2IzVmtSbXhoY21VZ1QzSnBaMmx1SUVObGNuUnBabWxqWVhSbE1JSUJJakFOQmdrcWhraUcKOXcwQkFRRUZBQU9DQVE0QU1JSUJDZ0tDQVFFQXV0QmpkQ0xEdHdMQlZCU0Y1ZU1OMkt3ckIxTmZmRVhRMjlRRAo1aVR0dzJFcEZXNVJJSllkMjNrYUpCMU5jZXpHWlg4a0Q0cGEyWHpFZW1MVEtJNWw0MU11b3FoWjczNVE3U3RWCkVjRFFTT2ZYTkZQdFMwb0hqb0pRdGF2QjM0ZmJNR3l4Mmx0MU9HUzRNMGtLUWpBNWR6OTJQYjNyZ1RKR0JhOW4KeTZtVThncjRuUHRSdklxZ3NxdjRtMFA3dVU1YjE3NzU1Y2JLSDVoMzIxWHVjMDU4Tzl4M2JHQ0NuRUJXWDdqeApjRGhkUEs1Ri9XRjVBQnl5cFhIQ0ZxUUd4M1NVbmtCQ0ZQSmRabnMra3BHVUZWZGhud3B6NjBtNnlJSzQ0eVR4CjZqR3JOTFEyM1dOK2gwU1lCZU5vb2JBWThydkpiVlZEaGJqSVhBTWtFNGQzVll1TlhRSURBUUFCbzRJQklqQ0MKQVI0d0RnWURWUjBQQVFIL0JBUURBZ1dnTUIwR0ExVWRKUVFXTUJRR0NDc0dBUVVGQndNQ0JnZ3JCZ0VGQlFjRApBVEFNQmdOVkhSTUJBZjhFQWpBQU1CMEdBMVVkRGdRV0JCUkt1NkJVUDZ0N2dpbFRPay9FdEdKQ3R6N3dTREFmCkJnTlZIU01FR0RBV2dCUWs2Rk5YWFh3MFFJZXA2NVRidXVFV2VQd3BwREJBQmdnckJnRUZCUWNCQVFRME1ESXcKTUFZSUt3WUJCUVVITUFHR0pHaDBkSEE2THk5dlkzTndMbU5zYjNWa1pteGhjbVV1WTI5dEwyOXlhV2RwYmw5agpZVEFqQmdOVkhSRUVIREFhZ2d3cUxtbGhiWGR2Y21zdWFXNkNDbWxoYlhkdmNtc3VhVzR3T0FZRFZSMGZCREV3Ckx6QXRvQ3VnS1lZbmFIUjBjRG92TDJOeWJDNWpiRzkxWkdac1lYSmxMbU52YlM5dmNtbG5hVzVmWTJFdVkzSnMKTUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFDSjMvTGNleE5pb0lWdUxoemhmbTZCeDV2SWk3T25CaHF1WUlDdwplNnArZ0prdE16ZFJQcDV0bk03dllBWmxMajVJOTByWDRuczhJc3dEbzJBN2wwYTRGZVJFclFmRklsZXQzbjIyCjUxVTZYVElCSks5c1FZT0FkU3pJUzV1OUNKSFpBUTF5WmxSd3BBR3RVWnhxL1dpcGFWUTRwNXhrcEJNMVlZSlAKNW1jQ09HcFErSnpORlpQc2daYUJncDBYL1BBZkNJRkkyZld5QWE2elBqRm0rdDVXUXIrZlBaT2VUS2VIbWVzVgo3UlZxUUdEb3Q0eTY1NklEdmdmU2ZLRnFIRW9XNDJVbDBxQ05hMS9keEJld3NIS1VWWE1ETkdiQlNVQjM4TG9YCm1OQ3hJQlVOUjR0TG1CQUxZT3hVMnZhSWRCd0xBc2YrcndnVnVjUGpCUTc2VWMwUQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
|
||||||
tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQzYwR04wSXNPM0FzRlUKRklYbDR3M1lyQ3NIYTE5OFJkRGIxQVBtSk8zRFlTa1ZibEVnbGgzYmVSb2tIVTF4N01abGZ5UVBpbHJaZk1SNgpZdE1vam1YalV5NmlxRm52ZmxEdEsxVVJ3TkJJNTljMFUrMUxTZ2VPZ2xDMXE4SGZoOXN3YkxIYVczVTRaTGd6ClNRcENNRGwzUDNZOXZldUJNa1lGcjJmTHFaVHlDdmljKzFHOGlxQ3lxL2liUS91NVRsdlh2dm5seHNvZm1IZmIKVmU1elRudzczSGRzWUlLY1FGWmZ1UEZ3T0YwOHJrWDlZWGtBSExLbGNjSVdwQWJIZEpTZVFFSVU4bDFtZXo2UwprWlFWVjJHZkNuUHJTYnJJZ3JqakpQSHFNYXMwdERiZFkzNkhSSmdGNDJpaHNCanl1OGx0VlVPRnVNaGNBeVFUCmgzZFZpNDFkQWdNQkFBRUNnZ0VBTGlseXZkNmVTcEYvZUxtV2lhTVV4NUxwa2dhWHpITkxCQnNNZUpqcytLL0EKVVdlZ1crTkVUdmlLalZ5QlI5SzRocG1IYldDa2lPUDBBQUwrQnlKQ3lvekNOQmJTSEdRejlwc1R5dzZBV1ZlUwpuYjlVWGx1VmFQRktKTTRqbXNydERuYjVic25WT2lGblErTDdTalkwNlFMUlFybjBvUWp0ZFJldUdBMFlQVU90CkhSYzNsMFg2ZHJqdkJYY2prWTQwWm9ZYkRrelJnU1JWbWVOUGFIbjZPR0NtYUVUMXVyK01qYVZ2ME9lbEdIWncKVzljSEIxaHNxRzUvMWU3V0RQN0l0cjkwTmg4ay81NVhiK3lQUnhsRFd5bWtZMzIvdFBtZzdESTRKV2tRRWt3cgpIZUtwODVTcE5ta1liRnVpVFppeU8zZDZ0aXZHNHhFZW8rSzFVVFU4c1FLQmdRRFRNSEU1RDFYVC9HbGR5VHNsCllrODRVL1N0NXUrK2RIUEt1Wmw2dVB0UGgxV1lrdnFRcmdrL05YanVud2xGN0Y3b2tWOGdPeWxreTYwYTZkcXIKeXZwN1ZJdXYzekVlc2h2NjNWMlpaVkMzcXZYSzFheit3Zmx3NitCZmVuRlY5S2NENHN0dTdwOFRPWmFGN01CUgo3YXZzaXVXbWtqdmM1TlVLRmVDRTY0SnZFUUtCZ1FEaWMrbWlNLzBodDN1ajhuOXgyMDFQZFNqbEpVaUc1NjNNCnRYZlBCdDJRT0NhaVluUFNFdTdXdm5pQWRFL2xrMm91cFRWam9LYmZPbDFyQjd6UzVhc2kxdVdDZDhlUy9UWGIKdU5iRmlNMDB4L3JxalMydCtQbTd4MVhrYTB4TFNSRDNmZ0tSQldSN3pscStkYWZ1WE1qelUxRnh5dTIycGphRgpIMEl3NEpCUmpRS0JnUUNOaWhMb0Rob1V5RCtKNXJzb00vb3FJMEtDWnB0WlJzendHbkg5cVFwdFk2Ti9iVXBYCk92emhpeUh3czAvUXVEbG5uejVrNktHMmR6Y2VLWXN2eGdzWUt6S3ZmV043VWgya2hVWWM3NlVvWTREMkh6MGgKUkxtNzc2cGg4enNRUTdiSHlQRlUrTUpPYlRNdnNOdTRUUlVEcEplRGl0QnFIRWVYeWMrKzVlUjJNUUtCZ0h2UgptVHVoWlpVYitEVEtrVGkyQ20yWnlBU1RBRGNUVW9xTjVyYUNNSDk4MUZNUnRmWjFkN1pmYXhBQmlQWWtSbmkrCnlKUnk4UXM1cEg2ek9tR3VSb2JFTGJYS3ZJcjRmSXhwWXJXYmVXaVV0L09yd2dCUUZHekNMNHEzeUgyWnMvYy8KSlRRYVdMa0JPY2pPR0VaUzRXVjZkeHZiTTJNZE9zNUxLeXdDZmFhNUFvR0FIQUE1eEN0dndOZE4xeExndkZ3RApPK2lyMDl1bXMxOFBzSVpmK1ZrWGtpcHF4MWNUT0hEanpPR01yWXV0M2FFeE00Zjd2ckFHRFMyY2pwZjM0T1JxCit4Y2gwWlNaQ2FDZmlnZG9OelNkcDFLcmo0cnFKdG5ZdS9CNDlDQlVoSDBNaCtSRWswQ0hHOVE4b3FOWFk0V0wKbVVOVTZMYUkwQWtvSzNVb2tWQVJEYXM9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K
|
tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQzYwR04wSXNPM0FzRlUKRklYbDR3M1lyQ3NIYTE5OFJkRGIxQVBtSk8zRFlTa1ZibEVnbGgzYmVSb2tIVTF4N01abGZ5UVBpbHJaZk1SNgpZdE1vam1YalV5NmlxRm52ZmxEdEsxVVJ3TkJJNTljMFUrMUxTZ2VPZ2xDMXE4SGZoOXN3YkxIYVczVTRaTGd6ClNRcENNRGwzUDNZOXZldUJNa1lGcjJmTHFaVHlDdmljKzFHOGlxQ3lxL2liUS91NVRsdlh2dm5seHNvZm1IZmIKVmU1elRudzczSGRzWUlLY1FGWmZ1UEZ3T0YwOHJrWDlZWGtBSExLbGNjSVdwQWJIZEpTZVFFSVU4bDFtZXo2UwprWlFWVjJHZkNuUHJTYnJJZ3JqakpQSHFNYXMwdERiZFkzNkhSSmdGNDJpaHNCanl1OGx0VlVPRnVNaGNBeVFUCmgzZFZpNDFkQWdNQkFBRUNnZ0VBTGlseXZkNmVTcEYvZUxtV2lhTVV4NUxwa2dhWHpITkxCQnNNZUpqcytLL0EKVVdlZ1crTkVUdmlLalZ5QlI5SzRocG1IYldDa2lPUDBBQUwrQnlKQ3lvekNOQmJTSEdRejlwc1R5dzZBV1ZlUwpuYjlVWGx1VmFQRktKTTRqbXNydERuYjVic25WT2lGblErTDdTalkwNlFMUlFybjBvUWp0ZFJldUdBMFlQVU90CkhSYzNsMFg2ZHJqdkJYY2prWTQwWm9ZYkRrelJnU1JWbWVOUGFIbjZPR0NtYUVUMXVyK01qYVZ2ME9lbEdIWncKVzljSEIxaHNxRzUvMWU3V0RQN0l0cjkwTmg4ay81NVhiK3lQUnhsRFd5bWtZMzIvdFBtZzdESTRKV2tRRWt3cgpIZUtwODVTcE5ta1liRnVpVFppeU8zZDZ0aXZHNHhFZW8rSzFVVFU4c1FLQmdRRFRNSEU1RDFYVC9HbGR5VHNsCllrODRVL1N0NXUrK2RIUEt1Wmw2dVB0UGgxV1lrdnFRcmdrL05YanVud2xGN0Y3b2tWOGdPeWxreTYwYTZkcXIKeXZwN1ZJdXYzekVlc2h2NjNWMlpaVkMzcXZYSzFheit3Zmx3NitCZmVuRlY5S2NENHN0dTdwOFRPWmFGN01CUgo3YXZzaXVXbWtqdmM1TlVLRmVDRTY0SnZFUUtCZ1FEaWMrbWlNLzBodDN1ajhuOXgyMDFQZFNqbEpVaUc1NjNNCnRYZlBCdDJRT0NhaVluUFNFdTdXdm5pQWRFL2xrMm91cFRWam9LYmZPbDFyQjd6UzVhc2kxdVdDZDhlUy9UWGIKdU5iRmlNMDB4L3JxalMydCtQbTd4MVhrYTB4TFNSRDNmZ0tSQldSN3pscStkYWZ1WE1qelUxRnh5dTIycGphRgpIMEl3NEpCUmpRS0JnUUNOaWhMb0Rob1V5RCtKNXJzb00vb3FJMEtDWnB0WlJzendHbkg5cVFwdFk2Ti9iVXBYCk92emhpeUh3czAvUXVEbG5uejVrNktHMmR6Y2VLWXN2eGdzWUt6S3ZmV043VWgya2hVWWM3NlVvWTREMkh6MGgKUkxtNzc2cGg4enNRUTdiSHlQRlUrTUpPYlRNdnNOdTRUUlVEcEplRGl0QnFIRWVYeWMrKzVlUjJNUUtCZ0h2UgptVHVoWlpVYitEVEtrVGkyQ20yWnlBU1RBRGNUVW9xTjVyYUNNSDk4MUZNUnRmWjFkN1pmYXhBQmlQWWtSbmkrCnlKUnk4UXM1cEg2ek9tR3VSb2JFTGJYS3ZJcjRmSXhwWXJXYmVXaVV0L09yd2dCUUZHekNMNHEzeUgyWnMvYy8KSlRRYVdMa0JPY2pPR0VaUzRXVjZkeHZiTTJNZE9zNUxLeXdDZmFhNUFvR0FIQUE1eEN0dndOZE4xeExndkZ3RApPK2lyMDl1bXMxOFBzSVpmK1ZrWGtpcHF4MWNUT0hEanpPR01yWXV0M2FFeE00Zjd2ckFHRFMyY2pwZjM0T1JxCit4Y2gwWlNaQ2FDZmlnZG9OelNkcDFLcmo0cnFKdG5ZdS9CNDlDQlVoSDBNaCtSRWswQ0hHOVE4b3FOWFk0V0wKbVVOVTZMYUkwQWtvSzNVb2tWQVJEYXM9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K
|
||||||
---
|
---
|
||||||
# 1Password → K8s Secret sync for Twilio credentials
|
# 1Password → K8s Secret sync for Twilio credentials
|
||||||
# Creates secret "twilio-credentials" with fields: AccountSid, AuthToken, DefaultFromNumber
|
# Creates secret "twilio-credentials" with fields: AccountSid, AuthToken, DefaultFromNumber
|
||||||
apiVersion: onepassword.com/v1
|
apiVersion: onepassword.com/v1
|
||||||
kind: OnePasswordItem
|
kind: OnePasswordItem
|
||||||
metadata:
|
metadata:
|
||||||
name: twilio-credentials
|
name: twilio-credentials
|
||||||
namespace: telephony
|
namespace: telephony
|
||||||
spec:
|
spec:
|
||||||
itemPath: "vaults/IAmWorkin/items/Twilio Account"
|
itemPath: "vaults/IAmWorkin/items/Twilio Account"
|
||||||
---
|
---
|
||||||
# Application configuration overlay
|
# Application configuration overlay
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: ConfigMap
|
kind: ConfigMap
|
||||||
metadata:
|
metadata:
|
||||||
name: telephony-config
|
name: telephony-config
|
||||||
namespace: telephony
|
namespace: telephony
|
||||||
data:
|
data:
|
||||||
appsettings.Production.json: |
|
appsettings.Production.json: |
|
||||||
{
|
{
|
||||||
"Telephony": {
|
"Telephony": {
|
||||||
"Provider": "asterisk",
|
"Provider": "asterisk",
|
||||||
"Twilio": {
|
"Twilio": {
|
||||||
"VoiceUrl": "https://telephony.flowercore.io/api/twilio/webhooks/voice/incoming",
|
"VoiceUrl": "https://telephony.flowercore.io/api/twilio/webhooks/voice/incoming",
|
||||||
"StatusCallbackUrl": "https://telephony.flowercore.io/api/twilio/webhooks/voice/status"
|
"StatusCallbackUrl": "https://telephony.flowercore.io/api/twilio/webhooks/voice/status"
|
||||||
},
|
},
|
||||||
"Asterisk": {
|
"Asterisk": {
|
||||||
"BaseUrl": "http://localhost:8088",
|
"BaseUrl": "http://localhost:8088",
|
||||||
"Username": "flowercore",
|
"Username": "flowercore",
|
||||||
"Password": "bluejay-asterisk-ari",
|
"Password": "bluejay-asterisk-ari",
|
||||||
"Application": "flowercore-pbx",
|
"Application": "flowercore-pbx",
|
||||||
"ReconnectDelaySeconds": 5,
|
"ReconnectDelaySeconds": 5,
|
||||||
"MaxReconnectDelaySeconds": 60
|
"MaxReconnectDelaySeconds": 60
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Ari": {
|
"Ari": {
|
||||||
"BaseUrl": "http://localhost:8088",
|
"BaseUrl": "http://localhost:8088",
|
||||||
"Username": "flowercore",
|
"Username": "flowercore",
|
||||||
"Password": "bluejay-asterisk-ari",
|
"Password": "bluejay-asterisk-ari",
|
||||||
"Application": "flowercore-pbx",
|
"Application": "flowercore-pbx",
|
||||||
"ReconnectDelaySeconds": 5,
|
"ReconnectDelaySeconds": 5,
|
||||||
"MaxReconnectDelaySeconds": 60
|
"MaxReconnectDelaySeconds": 60
|
||||||
},
|
},
|
||||||
"Tts": {
|
"Tts": {
|
||||||
"PiperUrl": "http://10.0.57.15:8500",
|
"PiperUrl": "http://10.0.57.15:8500",
|
||||||
"DefaultEngine": "piper",
|
"DefaultEngine": "piper",
|
||||||
"SampleRate": 8000
|
"SampleRate": 8000
|
||||||
},
|
},
|
||||||
"DatabaseProvider": "Sqlite",
|
"DatabaseProvider": "Sqlite",
|
||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
"DefaultConnection": "Data Source=/data/telephony.db"
|
"DefaultConnection": "Data Source=/data/telephony.db"
|
||||||
},
|
},
|
||||||
"Kestrel": {
|
"Kestrel": {
|
||||||
"Endpoints": {
|
"Endpoints": {
|
||||||
"Http": { "Url": "http://0.0.0.0:5100" }
|
"Http": { "Url": "http://0.0.0.0:5100" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
---
|
---
|
||||||
# Persistent volume for SQLite database
|
# Persistent volume for SQLite database
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolumeClaim
|
kind: PersistentVolumeClaim
|
||||||
metadata:
|
metadata:
|
||||||
name: telephony-data
|
name: telephony-data
|
||||||
namespace: telephony
|
namespace: telephony
|
||||||
spec:
|
spec:
|
||||||
accessModes: [ReadWriteOnce]
|
accessModes: [ReadWriteOnce]
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: 5Gi
|
storage: 5Gi
|
||||||
---
|
---
|
||||||
# Telephony web application
|
# Telephony web application
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: telephony-web
|
name: telephony-web
|
||||||
namespace: telephony
|
namespace: telephony
|
||||||
labels:
|
labels:
|
||||||
app: telephony-web
|
app: telephony-web
|
||||||
spec:
|
spec:
|
||||||
replicas: 1
|
replicas: 1
|
||||||
strategy:
|
strategy:
|
||||||
type: Recreate
|
type: Recreate
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app: telephony-web
|
app: telephony-web
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
app: telephony-web
|
app: telephony-web
|
||||||
spec:
|
spec:
|
||||||
securityContext:
|
securityContext:
|
||||||
fsGroup: 1654
|
fsGroup: 1654
|
||||||
initContainers:
|
initContainers:
|
||||||
- name: fix-data-perms
|
- name: fix-data-perms
|
||||||
image: busybox:latest
|
image: busybox:latest
|
||||||
command: ["sh", "-c", "chown -R 1654:1654 /data"]
|
command: ["sh", "-c", "chown -R 1654:1654 /data"]
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: telephony-data
|
- name: telephony-data
|
||||||
mountPath: /data
|
mountPath: /data
|
||||||
hostNetwork: true
|
hostNetwork: true
|
||||||
dnsPolicy: ClusterFirstWithHostNet
|
dnsPolicy: ClusterFirstWithHostNet
|
||||||
affinity:
|
affinity:
|
||||||
podAffinity:
|
podAffinity:
|
||||||
requiredDuringSchedulingIgnoredDuringExecution:
|
requiredDuringSchedulingIgnoredDuringExecution:
|
||||||
- labelSelector:
|
- labelSelector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app: asterisk
|
app: asterisk
|
||||||
topologyKey: kubernetes.io/hostname
|
topologyKey: kubernetes.io/hostname
|
||||||
containers:
|
containers:
|
||||||
- name: telephony-web
|
- name: telephony-web
|
||||||
image: localhost/fc-telephony-web:latest
|
image: localhost/fc-telephony-web:v20260324d
|
||||||
imagePullPolicy: Never
|
imagePullPolicy: Never
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 5100
|
- containerPort: 5100
|
||||||
name: http
|
name: http
|
||||||
env:
|
env:
|
||||||
- name: Telephony__Twilio__AccountSid
|
- name: Telephony__Twilio__AccountSid
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: twilio-credentials
|
name: twilio-credentials
|
||||||
key: AccountSid
|
key: AccountSid
|
||||||
optional: true
|
optional: true
|
||||||
- name: Telephony__Twilio__AuthToken
|
- name: Telephony__Twilio__AuthToken
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: twilio-credentials
|
name: twilio-credentials
|
||||||
key: AuthToken
|
key: AuthToken
|
||||||
optional: true
|
optional: true
|
||||||
- name: Telephony__Twilio__DefaultFromNumber
|
- name: Telephony__Twilio__DefaultFromNumber
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: twilio-credentials
|
name: twilio-credentials
|
||||||
key: DefaultFromNumber
|
key: DefaultFromNumber
|
||||||
optional: true
|
optional: true
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: telephony-config
|
- name: telephony-config
|
||||||
mountPath: /app/appsettings.Production.json
|
mountPath: /app/appsettings.Production.json
|
||||||
subPath: appsettings.Production.json
|
subPath: appsettings.Production.json
|
||||||
readOnly: true
|
readOnly: true
|
||||||
- name: telephony-data
|
- name: telephony-data
|
||||||
mountPath: /data
|
mountPath: /data
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
memory: 256Mi
|
memory: 256Mi
|
||||||
cpu: 100m
|
cpu: 100m
|
||||||
limits:
|
limits:
|
||||||
memory: 1Gi
|
memory: 1Gi
|
||||||
cpu: "1"
|
cpu: "1"
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
httpGet:
|
httpGet:
|
||||||
path: /health
|
path: /health
|
||||||
port: 5100
|
port: 5100
|
||||||
initialDelaySeconds: 30
|
initialDelaySeconds: 30
|
||||||
periodSeconds: 10
|
periodSeconds: 10
|
||||||
readinessProbe:
|
readinessProbe:
|
||||||
httpGet:
|
httpGet:
|
||||||
path: /health
|
path: /health
|
||||||
port: 5100
|
port: 5100
|
||||||
initialDelaySeconds: 10
|
initialDelaySeconds: 10
|
||||||
periodSeconds: 5
|
periodSeconds: 5
|
||||||
volumes:
|
volumes:
|
||||||
- name: telephony-config
|
- name: telephony-config
|
||||||
configMap:
|
configMap:
|
||||||
name: telephony-config
|
name: telephony-config
|
||||||
- name: telephony-data
|
- name: telephony-data
|
||||||
persistentVolumeClaim:
|
persistentVolumeClaim:
|
||||||
claimName: telephony-data
|
claimName: telephony-data
|
||||||
---
|
---
|
||||||
# ClusterIP service
|
# ClusterIP service
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: telephony-web
|
name: telephony-web
|
||||||
namespace: telephony
|
namespace: telephony
|
||||||
spec:
|
spec:
|
||||||
selector:
|
selector:
|
||||||
app: telephony-web
|
app: telephony-web
|
||||||
ports:
|
ports:
|
||||||
- port: 5100
|
- port: 5100
|
||||||
targetPort: 5100
|
targetPort: 5100
|
||||||
name: http
|
name: http
|
||||||
---
|
---
|
||||||
# Traefik IngressRoute — public via Cloudflare (primary: flowercore.io)
|
# Traefik IngressRoute — public via Cloudflare (primary: flowercore.io)
|
||||||
apiVersion: traefik.io/v1alpha1
|
apiVersion: traefik.io/v1alpha1
|
||||||
kind: IngressRoute
|
kind: IngressRoute
|
||||||
metadata:
|
metadata:
|
||||||
name: telephony-web
|
name: telephony-web
|
||||||
namespace: telephony
|
namespace: telephony
|
||||||
spec:
|
spec:
|
||||||
entryPoints:
|
entryPoints:
|
||||||
- websecure
|
- websecure
|
||||||
routes:
|
routes:
|
||||||
- kind: Rule
|
- kind: Rule
|
||||||
match: Host(`telephony.flowercore.io`)
|
match: Host(`telephony.flowercore.io`)
|
||||||
services:
|
services:
|
||||||
- name: telephony-web
|
- name: telephony-web
|
||||||
port: 5100
|
port: 5100
|
||||||
- kind: Rule
|
- kind: Rule
|
||||||
match: Host(`telephony.iamwork.in`)
|
match: Host(`telephony.iamwork.in`)
|
||||||
services:
|
services:
|
||||||
- name: telephony-web
|
- name: telephony-web
|
||||||
port: 5100
|
port: 5100
|
||||||
tls:
|
tls:
|
||||||
secretName: cf-origin-flowercore-io
|
secretName: cf-origin-flowercore-io
|
||||||
---
|
---
|
||||||
# NetworkPolicy: deny-all baseline + Traefik ingress + SIP/RTP ingress + DNS egress + TTS egress
|
# NetworkPolicy: deny-all baseline + Traefik ingress + SIP/RTP ingress + DNS egress + TTS egress
|
||||||
apiVersion: networking.k8s.io/v1
|
apiVersion: networking.k8s.io/v1
|
||||||
kind: NetworkPolicy
|
kind: NetworkPolicy
|
||||||
metadata:
|
metadata:
|
||||||
name: telephony-netpol
|
name: telephony-netpol
|
||||||
namespace: telephony
|
namespace: telephony
|
||||||
spec:
|
spec:
|
||||||
podSelector: {}
|
podSelector: {}
|
||||||
policyTypes:
|
policyTypes:
|
||||||
- Ingress
|
- Ingress
|
||||||
- Egress
|
- Egress
|
||||||
ingress:
|
ingress:
|
||||||
# Allow Traefik ingress controller
|
# Allow Traefik ingress controller
|
||||||
- from:
|
- from:
|
||||||
- namespaceSelector:
|
- namespaceSelector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
kubernetes.io/metadata.name: traefik-system
|
kubernetes.io/metadata.name: traefik-system
|
||||||
# Allow Selenium Grid for automated UI testing
|
# Allow Selenium Grid for automated UI testing
|
||||||
- from:
|
- from:
|
||||||
- namespaceSelector:
|
- namespaceSelector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
kubernetes.io/metadata.name: selenium
|
kubernetes.io/metadata.name: selenium
|
||||||
ports:
|
ports:
|
||||||
- port: 5100
|
- port: 5100
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
# Allow SIP/RTP from external sources (Yealink phones, Twilio SIP trunk)
|
# Allow SIP/RTP from external sources (Yealink phones, Twilio SIP trunk)
|
||||||
- from:
|
- from:
|
||||||
- ipBlock:
|
- ipBlock:
|
||||||
cidr: 0.0.0.0/0
|
cidr: 0.0.0.0/0
|
||||||
ports:
|
ports:
|
||||||
- port: 5060
|
- port: 5060
|
||||||
protocol: UDP
|
protocol: UDP
|
||||||
- port: 5060
|
- port: 5060
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
- port: 10000
|
- port: 10000
|
||||||
endPort: 20000
|
endPort: 20000
|
||||||
protocol: UDP
|
protocol: UDP
|
||||||
egress:
|
egress:
|
||||||
# Allow DNS resolution (CoreDNS in kube-system)
|
# Allow DNS resolution (CoreDNS in kube-system)
|
||||||
- to:
|
- to:
|
||||||
- namespaceSelector:
|
- namespaceSelector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
kubernetes.io/metadata.name: kube-system
|
kubernetes.io/metadata.name: kube-system
|
||||||
ports:
|
ports:
|
||||||
- port: 53
|
- port: 53
|
||||||
protocol: UDP
|
protocol: UDP
|
||||||
- port: 53
|
- port: 53
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
# Allow Piper TTS on edge1 (10.0.57.15:8500)
|
# Allow Piper TTS on edge1 (10.0.57.15:8500)
|
||||||
- to:
|
- to:
|
||||||
- ipBlock:
|
- ipBlock:
|
||||||
cidr: 10.0.57.15/32
|
cidr: 10.0.57.15/32
|
||||||
ports:
|
ports:
|
||||||
- port: 8500
|
- port: 8500
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
# Allow Twilio API outbound (HTTPS)
|
# Allow Twilio API outbound (HTTPS)
|
||||||
- to:
|
- to:
|
||||||
- ipBlock:
|
- ipBlock:
|
||||||
cidr: 0.0.0.0/0
|
cidr: 0.0.0.0/0
|
||||||
except:
|
except:
|
||||||
- 10.0.0.0/8
|
- 10.0.0.0/8
|
||||||
- 172.16.0.0/12
|
- 172.16.0.0/12
|
||||||
- 192.168.0.0/16
|
- 192.168.0.0/16
|
||||||
ports:
|
ports:
|
||||||
- port: 443
|
- port: 443
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
# Allow SIP/RTP responses (Asterisk → phones and Twilio)
|
# Allow SIP/RTP responses (Asterisk → phones and Twilio)
|
||||||
- to:
|
- to:
|
||||||
- ipBlock:
|
- ipBlock:
|
||||||
cidr: 0.0.0.0/0
|
cidr: 0.0.0.0/0
|
||||||
ports:
|
ports:
|
||||||
- port: 5060
|
- port: 5060
|
||||||
protocol: UDP
|
protocol: UDP
|
||||||
- port: 5060
|
- port: 5060
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
- port: 10000
|
- port: 10000
|
||||||
endPort: 20000
|
endPort: 20000
|
||||||
protocol: UDP
|
protocol: UDP
|
||||||
# Allow 1Password Connect for secret sync
|
# Allow 1Password Connect for secret sync
|
||||||
- to:
|
- to:
|
||||||
- namespaceSelector:
|
- namespaceSelector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
kubernetes.io/metadata.name: onepassword-system
|
kubernetes.io/metadata.name: onepassword-system
|
||||||
---
|
---
|
||||||
# TLS Certificate for internal hostname via cert-manager
|
# TLS Certificate for internal hostname via cert-manager
|
||||||
apiVersion: cert-manager.io/v1
|
apiVersion: cert-manager.io/v1
|
||||||
kind: Certificate
|
kind: Certificate
|
||||||
metadata:
|
metadata:
|
||||||
name: telephony-internal-tls
|
name: telephony-internal-tls
|
||||||
namespace: telephony
|
namespace: telephony
|
||||||
spec:
|
spec:
|
||||||
secretName: telephony-internal-tls
|
secretName: telephony-internal-tls
|
||||||
issuerRef:
|
issuerRef:
|
||||||
name: step-ca-acme
|
name: step-ca-acme
|
||||||
kind: ClusterIssuer
|
kind: ClusterIssuer
|
||||||
dnsNames:
|
dnsNames:
|
||||||
- telephony.iamworkin.lan
|
- telephony.iamworkin.lan
|
||||||
---
|
---
|
||||||
# Traefik IngressRoute — internal LAN access
|
# Traefik IngressRoute — internal LAN access
|
||||||
apiVersion: traefik.io/v1alpha1
|
apiVersion: traefik.io/v1alpha1
|
||||||
kind: IngressRoute
|
kind: IngressRoute
|
||||||
metadata:
|
metadata:
|
||||||
name: telephony-web-internal
|
name: telephony-web-internal
|
||||||
namespace: telephony
|
namespace: telephony
|
||||||
spec:
|
spec:
|
||||||
entryPoints:
|
entryPoints:
|
||||||
- websecure
|
- websecure
|
||||||
routes:
|
routes:
|
||||||
- kind: Rule
|
- kind: Rule
|
||||||
match: Host(`telephony.iamworkin.lan`)
|
match: Host(`telephony.iamworkin.lan`)
|
||||||
services:
|
services:
|
||||||
- name: telephony-web
|
- name: telephony-web
|
||||||
port: 5100
|
port: 5100
|
||||||
tls:
|
tls:
|
||||||
secretName: telephony-internal-tls
|
secretName: telephony-internal-tls
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user