Commit Graph

365 Commits

Author SHA1 Message Date
Andrew Stoltz
9d0da584af Add The Lounge web IRC client 2026-04-16 19:10:10 -05:00
Andrew Stoltz
4f33d7a053 fix(telephony): chown /shared-tts in initContainer + harden security context
Two follow-ups to the Piper TTS wire-up landed in d3ffad9:

1. Telephony-web runs as uid 1654 (non-root), but the hostPath at
   /tmp/tts-audio is owned by root:root 0755. Pod couldn't write .sln16
   files — every Piper call would succeed at the HTTP layer and then
   fall back to the sound map when File.WriteAllBytesAsync threw
   "Permission denied." Extend the existing fix-data-perms initContainer
   to chown the shared-tts mount too (0755 world-readable, so the
   Asterisk pod — running as a different uid — can still read).

2. Pod security context now explicitly sets runAsNonRoot: true + runAsUser
   1654 + runAsGroup 1654 (cluster policy), matching the pattern used
   by every other FlowerCore service.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 16:29:21 -05:00
Andrew Stoltz
d3ffad9190 fix(telephony): PiperUrl 10.0.57.15 → .17 + shared-tts hostPath for TTS playback
Piper was never reachable on 10.0.57.15 — edge1's actual address is
10.0.57.17 (SSH config, project_edge1_sdcard memory). Every telephony
prompt hit the 8s HttpClient timeout and fell back to the built-in sound
map (vm-advopts, vm-goodbye, beep) instead of speaking the real workflow
text. Verified from noc1: `curl http://10.0.57.17:8500/health` returns
HTTP 200 in 6ms, `POST /tts` returns a 16kHz mono WAV in 606ms.

Changes:

- apps/telephony/telephony.yaml
  - `Tts.PiperUrl` → `http://10.0.57.17:8500`
  - NetworkPolicy egress allow → `10.0.57.17/32:8500`
  - Header comment now documents the POST /tts {"text":"..."} contract
  - telephony-web pod mounts `/shared-tts` from hostPath `/tmp/tts-audio`
    (rke2-agent1). This is where `AsteriskProvider.SpeakTextAsync` writes
    the synthesized .sln16 before calling ARI `Play sound:tts/<name>`.

- apps/asterisk/deployment.yaml
  - Asterisk pod mounts the same hostPath at
    `/var/lib/asterisk/sounds/tts` so it can read and play what
    telephony-web wrote. Both deployments have
    `nodeSelector: kubernetes.io/hostname: rke2-agent1` so the hostPath
    is guaranteed to be the same directory.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 16:19:48 -05:00
Andrew Stoltz
403d061664 fix(asterisk): hostAlias downloads.asterisk.org so sounds actually download
CoreDNS wildcard for iamworkin.lan catches unresolved names and returns
the Traefik VIP (10.0.56.200), so downloads.asterisk.org from inside a
pod returns 404 from Traefik rather than the real Sangoma mirror. Pin
the real IP (165.22.184.19 = oss-downloads.sangoma.com) via hostAliases
so curl reaches the actual server.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 15:54:39 -05:00
Andrew Stoltz
45a2cb3f93 fix(asterisk): curl -k for sounds download — cluster TLS MITM
Cluster egress goes through a step-ca-fronted TLS proxy that install-sounds
doesn't trust ("SSL certificate problem: self-signed certificate"). The
Asterisk core sounds tarball is a public artifact; integrity is enforced
downstream when Asterisk plays the file.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 15:48:34 -05:00
Andrew Stoltz
e1922564ae fix(asterisk): actually install core sounds (en, ulaw 1.6.1)
The install-sounds init container was a stub that left /var/lib/asterisk/sounds/en
empty. Result: every SpeakText fallback path (vm-advopts, vm-goodbye, characters:*,
digits/*, beep, pbx-invalid) resolved to a missing file, Asterisk silently failed
each Playback, zero RTP was produced, and callers heard dead air. This is why
dialing *0 (Settings Menu) or *100 (Debug IVR) "picks up quietly" — there is
literally nothing to stream.

Replaced the stub with alpine:3.20 + curl + tar that downloads the pinned
asterisk-core-sounds-en-ulaw-1.6.1.tar.gz (~10 MB) from downloads.asterisk.org
and unpacks it into the sounds emptyDir. Idempotent — skips download if
vm-goodbye is already present.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 15:42:58 -05:00
Andrew Stoltz
7762a0079a Add K8s deployment manifests for SignalControl, MessageBoard, Chat, TTS Reader
Full deployment manifests (Namespace, Deployment, Service, Certificate,
IngressRoute) for 4 new FlowerCore services with port 8080, ClusterIP
on port 80, cert-manager step-ca-acme TLS, and /metrics/prometheus
health probes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 20:23:55 -05:00
Andrew Stoltz
ab7435a43a Update Agent Zero, Asterisk, and Telephony K8s manifests
- Update agent-zero deployment configuration
- Update Asterisk configmap and deployment
- Update telephony service manifest

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 19:12:08 -05:00
Andrew Stoltz
53234bfcc8 Fix K8s sync script: use grep instead of python3
bitnami/kubectl image doesn't have python3. Replaced all python3
JSON parsing with grep/cut for auth token and connection data.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 23:02:02 -05:00
Andrew Stoltz
cf572c167f Update Guacamole: branding JAR, K8s sync CronJob
- Updated bluejay-branding-1.0.0.jar with gold accents, hover fix,
  icon fix, pinstripe patterns, Blue Jay SVG logo
- Added guac-k8s-sync CronJob: runs every 2min, auto-updates pod
  names in Kubernetes exec connections when pods restart
- Fixed secret reference (guacamole-credentials, not guacamole-db-credentials)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 22:49:48 -05:00
Andrew Stoltz
7d5d0f86e7 Add signage service ingress manifests 2026-04-09 15:09:08 -05:00
Andrew Stoltz
8f59322329 Add step-ca TLS certs for mysql, php, desktop, signage, fc-landing
RKE2 Traefik has no ACME certResolver configured, so IngressRoutes
using certResolver: step-ca silently fall back to the Traefik default
self-signed cert. Fix by using cert-manager Certificate resources with
the step-ca-acme ClusterIssuer and tls.secretName in IngressRoutes.

- fc-landing: Add Certificate, change tls: {} to tls.secretName
- fc-mysql: New app (Certificate + IngressRoute only)
- fc-php: New app (Certificate + IngressRoute only)
- fc-desktop: New app (Certificate + IngressRoute only)
- fc-signage: New app (Certificate + IngressRoute, plus HTTP route for players)

Deployments/Services for mysql/php/desktop/signage are managed by
deploy scripts, not ArgoCD. These apps only manage TLS + ingress.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 18:20:23 -05:00
Claude Code
8f8290e0da Increase ctx to 8192 (system prompt + 21 tools need >2048) 2026-04-08 20:07:27 +00:00
Claude Code
607192aaec Reduce ctx to 2048 for Pi 5 CPU speed 2026-04-08 19:40:52 +00:00
Claude Code
072d64a5e9 Fix model config: write config.json not config.yaml (plugin reads JSON) 2026-04-08 19:22:16 +00:00
Claude Code
acb19bee9c Write Ollama model config before initialize.sh (fix OpenRouter default) 2026-04-08 19:15:43 +00:00
Claude Code
e6fbe2d22b Mount extensions+theme directly in main container (symlinks lost by initialize.sh) 2026-04-08 18:12:07 +00:00
Claude Code
dbd6769537 Reference split tools ConfigMaps (tools-a/b/c) in init container 2026-04-08 18:09:55 +00:00
Claude Code
0af47f893a Split bluejay-tools into 3 ConfigMaps (K8s 262K annotation limit) 2026-04-08 18:09:49 +00:00
Claude Code
d16f72f089 Enable Blue Jay profile: init container, ConfigMap volumes, tools, extensions, theme 2026-04-08 18:07:13 +00:00
Claude Code
36e7369609 Add Blue Jay profile ConfigMaps (21 tools, prompts, extensions, theme) 2026-04-08 18:07:06 +00:00
Claude Code
67e41febf5 Add agent-zero egress to monitoring NetworkPolicy for blackbox probes 2026-04-08 17:34:16 +00:00
Claude Code
c9f07108bd Fix edge1 Ollama IP (.15->.17), add monitoring ingress, add init container 2026-04-08 17:30:22 +00:00
Claude Code
f3919cf728 Add cert-manager Certificate for intranet ACME TLS auto-renewal 2026-04-05 08:47:42 -05:00
Claude Code
56442ecfbc Replace nginx+ConfigMap intranet with Blazor Server app
Replaces the 188KB ConfigMap-embedded HTML with a proper Blazor Server
deployment (fc-intranet-web:latest on port 5300). The old nginx deployment,
ConfigMaps (intranet-html, intranet-nginx-conf), and all embedded HTML are
removed. The intranet is now a .NET 10 Blazor app with live health monitoring,
REST API, 49 pages, and the unified Blue Jay theme.

Source: github.com/astoltz/FlowerCore.Intranet.Web
2026-04-04 19:29:28 -05:00
Andrew Stoltz
a07b6311b9 Add Blue Jay branding, kubectl-proxy, RBAC, and properties to Guacamole
- guacamole-branding ConfigMap with Blue Jay dark theme CSS
- guacamole-properties ConfigMap with ban/TOTP/session config
- kubectl-proxy sidecar on guacd for K8s pod exec connections
- guacd-exec ServiceAccount + ClusterRole/Binding for pod exec RBAC
- Volume mounts for branding JAR and properties on guacamole webapp

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 14:22:51 -05:00
Claude Code
331ae14d3f Update intranet: fcadmin links, Guacamole connections, 1Password deep-links 2026-04-03 13:40:09 -05:00
Claude Code
b291d0360b Update intranet HTML — deep cleanup 2026-03-28
- OpenVPN 9 servers, WiFi portal, Signage+RemoteDesktop on K8s
- Print.Web HTTPS via noc-proxy, 530 tests, 21 pages, 15 MCP
- Monitoring: 36 scrape jobs, 25 alert rules, 12 Grafana dashboards
- Remove BlueJay-Employee SSID (factory reset), fix WiFi to 4 SSIDs
- Fix Guacamole URL (guac -> guacamole), noc1 SSH typo, pfSense WAN igc3
- Add Signage, RemoteDesktop, WiFi Portal to DNS/service tables
- Update ArgoCD 22 apps, 41 namespaces, 49 IngressRoutes, Traefik v3.6.10
- IRC Anope marked CrashLoopBackOff, monitoring moved to K8s
- Total: 21,437+ tests across 13 services
2026-03-28 14:34:25 -05:00
Andrew M. Stoltz
090b29933f telephony-web v20260325d: global search, error pages, quick-create wizard 2026-03-25 17:58:56 -05:00
Andrew M. Stoltz
987b73c537 telephony-web v20260325c: workflow config validation, enhanced health checks, response compression, Serilog request logging 2026-03-25 17:47:27 -05:00
Andrew M. Stoltz
bf12474de9 telephony-web v20260325b: add SMS UnreadCount/LastMessagePreview columns to schema drift 2026-03-25 08:19:58 -05:00
Andrew M. Stoltz
f366dd5c90 telephony-web v20260325a: fix billing/RBAC 500s — replace IDbContextFactory with direct TelephonyDbContext injection 2026-03-25 08:11:59 -05:00
Andrew M. Stoltz
50146f8355 telephony-web v20260324n: rebuild-schema admin endpoint for production DB migration 2026-03-24 19:45:06 -05:00
Andrew M. Stoltz
ace06c5fb9 telephony-web v20260324m: model-driven schema drift — auto-creates ALL missing tables 2026-03-24 19:28:08 -05:00
Andrew M. Stoltz
7ed834f056 telephony-web v20260324l: schema drift fix for CustomRoles table 2026-03-24 19:03:26 -05:00
Andrew M. Stoltz
2b04c9e292 telephony-web v20260324k: RBAC policy editor, billing dashboard, 11081 tests ALL PASS 2026-03-24 18:55:03 -05:00
Andrew M. Stoltz
fafc2e510b telephony-web v20260324j: recording playback, SMS enhancements, notifications polish, dashboard shortcuts, all 11049 tests pass 2026-03-24 18:22:46 -05:00
Andrew M. Stoltz
fb1c622e62 telephony-web v20260324i: break-glass UI, 5 MCP tools, survey editor config, step palette 2026-03-24 17:37:19 -05:00
Andrew M. Stoltz
40cb7faef5 telephony-web v20260324h: setup wizard, REST smoke tests, survey route fix 2026-03-24 17:16:09 -05:00
Andrew M. Stoltz
bd79279b28 telephony-web v20260324g: schema drift fix (BridgeEvents, SurveyResponses tables), survey route fix 2026-03-24 16:53:21 -05:00
Andrew M. Stoltz
35b6b4f8e5 telephony-web v20260324f: remove Scalar/OpenApi packages (Swashbuckle conflict) 2026-03-24 16:06:11 -05:00
Andrew M. Stoltz
8d8b76c82b Fix telephony-web: revert Scalar (Swashbuckle conflict), use v20260324e 2026-03-24 16:02:32 -05:00
Andrew M. Stoltz
f3fde15002 Update telephony-web image to v20260324d, resolve merge conflicts 2026-03-24 15:55:52 -05:00
Andrew M. Stoltz
42d2894ed1 Update telephony-web image tag to v20260324d (Scalar API docs, webhook config, surveys, templates, member portal) 2026-03-24 15:55:40 -05:00
Claude Code
848288af7a Fix Traefik dashboard link — point to :8080/dashboard/ not catchall 404 2026-03-22 01:29:18 -05:00
780e3fb681 feat: add K8s exec RBAC + guacd ServiceAccount
Adds guacd-exec ServiceAccount, ClusterRole (pods/exec),
and ClusterRoleBinding for Kubernetes protocol support.
2026-03-22 06:25:11 +00:00
6040614016 feat: Blue Jay branding + 1Password vault extension
Custom image fc-guacamole:bluejay with:
- Blue Jay dark theme (CSS, login, header)
- 1Password Connect vault provider
- guacamole.properties ConfigMap
- Structured Logback logging
2026-03-22 06:15:01 +00:00
Claude Code
3872707bfb Update intranet: DNS-first URLs, 1Password deep-links, Pi fleet, monitoring
Replace all device IPs with iamworkin.lan DNS names. 46 1Password
deep-links. 22 ArgoCD apps, PVC inventory, Pi fleet services,
Print.Web, Selenium Grid, Guacamole connections. Zero hardcoded
passwords.
2026-03-22 01:04:39 -05:00
Andrew M. Stoltz
2aad3a698f Try inband DTMF detection for AX83H
Phone negotiates RFC4733 but may not actually send telephone-event
RTP packets. Inband detects DTMF from audio stream directly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 12:45:28 -05:00
Andrew M. Stoltz
b37b5f6d0d Add digit map + DTMF + disable local star codes in Yealink provisioning
Root cause: Yealink AX83H intercepts *0 locally as voicemail access,
never sending it to the SIP server. Fix:
- dialplan.digitmap sends all * codes to server
- DTMF set to RFC2833 for Asterisk ARI compatibility
- Local pickup/voicemail features disabled
- key_as_send enabled for immediate dial

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 12:39:16 -05:00