From 94fd360d02740661e0b3e30becea055c702a4c27 Mon Sep 17 00:00:00 2001 From: masami-agent Date: Fri, 1 May 2026 10:59:24 +0000 Subject: [PATCH 1/6] feat(helm): add Gateway Deployment + Service templates When gateway.enabled=true, the chart now creates: - Gateway Deployment (openab-gateway container) - Gateway Service (ClusterIP :8080) - Gateway Secret (GATEWAY_WS_TOKEN, TEAMS_APP_SECRET) TEAMS_* env vars are injected into the gateway container (not the agent container). Condition: appId AND appSecret both set (fail-closed). Also adds gateway.image, gateway.tag, and gateway.teams.* values. Closes #675 --- charts/openab/templates/gateway-secret.yaml | 26 +++++ charts/openab/templates/gateway.yaml | 104 ++++++++++++++++++++ charts/openab/values.yaml | 12 +++ 3 files changed, 142 insertions(+) create mode 100644 charts/openab/templates/gateway-secret.yaml create mode 100644 charts/openab/templates/gateway.yaml diff --git a/charts/openab/templates/gateway-secret.yaml b/charts/openab/templates/gateway-secret.yaml new file mode 100644 index 00000000..5b2c26fc --- /dev/null +++ b/charts/openab/templates/gateway-secret.yaml @@ -0,0 +1,26 @@ +{{- range $name, $cfg := .Values.agents }} +{{- if and (ne (include "openab.agentEnabled" $cfg) "false") ($cfg.gateway).enabled }} +{{- $d := dict "ctx" $ "agent" (printf "%s-gateway" $name) "cfg" $cfg }} +{{- $hasToken := ($cfg.gateway).token }} +{{- $hasTeams := and (($cfg.gateway).teams).appId (($cfg.gateway).teams).appSecret }} +{{- if or $hasToken $hasTeams }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "openab.agentFullname" $d }} + labels: + {{- include "openab.labels" $d | nindent 4 }} + annotations: + "helm.sh/resource-policy": keep +type: Opaque +data: + {{- if $hasToken }} + gateway-ws-token: {{ $cfg.gateway.token | b64enc | quote }} + {{- end }} + {{- if $hasTeams }} + teams-app-secret: {{ ($cfg.gateway).teams.appSecret | b64enc | quote }} + {{- end }} +{{- end }} +{{- end }} +{{- end }} diff --git a/charts/openab/templates/gateway.yaml b/charts/openab/templates/gateway.yaml new file mode 100644 index 00000000..4f433b2d --- /dev/null +++ b/charts/openab/templates/gateway.yaml @@ -0,0 +1,104 @@ +{{- range $name, $cfg := .Values.agents }} +{{- if and (ne (include "openab.agentEnabled" $cfg) "false") ($cfg.gateway).enabled }} +{{- $d := dict "ctx" $ "agent" (printf "%s-gateway" $name) "cfg" $cfg }} +{{- $hasTeams := and (($cfg.gateway).teams).appId (($cfg.gateway).teams).appSecret }} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "openab.agentFullname" $d }} + labels: + {{- include "openab.labels" $d | nindent 4 }} +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + {{- include "openab.selectorLabels" $d | nindent 6 }} + template: + metadata: + labels: + {{- include "openab.selectorLabels" $d | nindent 8 }} + spec: + {{- with $.Values.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: gateway + image: {{ printf "%s:%s" (($cfg.gateway).image | default "ghcr.io/openabdev/openab-gateway") (($cfg.gateway).tag | default $.Chart.AppVersion) }} + imagePullPolicy: {{ $.Values.image.pullPolicy }} + {{- with $.Values.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http + containerPort: 8080 + protocol: TCP + env: + {{- if ($cfg.gateway).token }} + - name: GATEWAY_WS_TOKEN + valueFrom: + secretKeyRef: + name: {{ include "openab.agentFullname" $d }} + key: gateway-ws-token + {{- end }} + {{- if $hasTeams }} + - name: TEAMS_APP_ID + value: {{ ($cfg.gateway).teams.appId | quote }} + - name: TEAMS_APP_SECRET + valueFrom: + secretKeyRef: + name: {{ include "openab.agentFullname" $d }} + key: teams-app-secret + {{- if ($cfg.gateway).teams.oauthEndpoint }} + - name: TEAMS_OAUTH_ENDPOINT + value: {{ ($cfg.gateway).teams.oauthEndpoint | quote }} + {{- end }} + {{- if ($cfg.gateway).teams.openidMetadata }} + - name: TEAMS_OPENID_METADATA + value: {{ ($cfg.gateway).teams.openidMetadata | quote }} + {{- end }} + {{- if ($cfg.gateway).teams.allowedTenants }} + - name: TEAMS_ALLOWED_TENANTS + value: {{ ($cfg.gateway).teams.allowedTenants | join "," | quote }} + {{- end }} + {{- if ($cfg.gateway).teams.webhookPath }} + - name: TEAMS_WEBHOOK_PATH + value: {{ ($cfg.gateway).teams.webhookPath | quote }} + {{- end }} + {{- end }} + - name: RUST_LOG + value: "info" + livenessProbe: + httpGet: + path: /health + port: http + initialDelaySeconds: 5 + periodSeconds: 30 + readinessProbe: + httpGet: + path: /health + port: http + initialDelaySeconds: 3 + periodSeconds: 10 +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "openab.agentFullname" $d }} + labels: + {{- include "openab.labels" $d | nindent 4 }} +spec: + type: ClusterIP + ports: + - port: 8080 + targetPort: http + protocol: TCP + name: http + selector: + {{- include "openab.selectorLabels" $d | nindent 4 }} +{{- end }} +{{- end }} diff --git a/charts/openab/values.yaml b/charts/openab/values.yaml index 54661a38..527dc297 100644 --- a/charts/openab/values.yaml +++ b/charts/openab/values.yaml @@ -199,6 +199,18 @@ agents: platform: "telegram" # default platform when gateway is enabled token: "" # optional shared secret (injected via GATEWAY_WS_TOKEN env var) botUsername: "" # optional, for @mention gating + image: "ghcr.io/openabdev/openab-gateway" # gateway container image + tag: "" # defaults to Chart.AppVersion + # MS Teams adapter config (gateway-side env vars) + # See docs/msteams-enterprise.md for full setup guide + teams: + appId: "" # Azure Entra ID application (client) ID → TEAMS_APP_ID + appSecret: "" # Azure Entra ID client secret → TEAMS_APP_SECRET + # ⚠️ Required for Single Tenant bots — use tenant-specific endpoint + oauthEndpoint: "" # → TEAMS_OAUTH_ENDPOINT + openidMetadata: "" # Override for sovereign clouds → TEAMS_OPENID_METADATA + allowedTenants: [] # List of tenant IDs → TEAMS_ALLOWED_TENANTS + webhookPath: "" # Gateway default: /webhook/teams → TEAMS_WEBHOOK_PATH # Scheduled messages — config-driven cron (ADR: basic-cronjob) # Each entry sends a message to the agent at the specified schedule. # Example: From 4e2a0376746c9c6bbe18da2059d84a8b7913486c Mon Sep 17 00:00:00 2001 From: masami-agent Date: Fri, 1 May 2026 11:57:59 +0000 Subject: [PATCH 2/6] =?UTF-8?q?fix(helm):=20address=20NIT=20findings=20?= =?UTF-8?q?=E2=80=94=20resources,=20checksum,=20strategy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add configurable resources block (gateway.resources in values.yaml) - Add checksum/config annotation for automatic rollout on config change - Make strategy configurable (gateway.strategy, default: Recreate) --- charts/openab/templates/gateway.yaml | 8 +++++++- charts/openab/values.yaml | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/charts/openab/templates/gateway.yaml b/charts/openab/templates/gateway.yaml index 4f433b2d..7a9e5ba8 100644 --- a/charts/openab/templates/gateway.yaml +++ b/charts/openab/templates/gateway.yaml @@ -12,12 +12,14 @@ metadata: spec: replicas: 1 strategy: - type: Recreate + type: {{ (($cfg.gateway).strategy) | default "Recreate" }} selector: matchLabels: {{- include "openab.selectorLabels" $d | nindent 6 }} template: metadata: + annotations: + checksum/config: {{ $cfg.gateway | toJson | sha256sum }} labels: {{- include "openab.selectorLabels" $d | nindent 8 }} spec: @@ -84,6 +86,10 @@ spec: port: http initialDelaySeconds: 3 periodSeconds: 10 + {{- with ($cfg.gateway).resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} --- apiVersion: v1 kind: Service diff --git a/charts/openab/values.yaml b/charts/openab/values.yaml index 527dc297..0bb60696 100644 --- a/charts/openab/values.yaml +++ b/charts/openab/values.yaml @@ -201,6 +201,8 @@ agents: botUsername: "" # optional, for @mention gating image: "ghcr.io/openabdev/openab-gateway" # gateway container image tag: "" # defaults to Chart.AppVersion + strategy: "Recreate" # Recreate (default, preserves WS connections) or RollingUpdate + resources: {} # e.g. { requests: { cpu: 50m, memory: 64Mi }, limits: { memory: 128Mi } } # MS Teams adapter config (gateway-side env vars) # See docs/msteams-enterprise.md for full setup guide teams: From 0eecedcd578037e8a6395a0e04c440c975baae2a Mon Sep 17 00:00:00 2001 From: masami-agent Date: Fri, 1 May 2026 13:33:27 +0000 Subject: [PATCH 3/6] fix(helm): prevent nameOverride collision between agent and gateway MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When agents..nameOverride is set, openab.agentFullname returns the override verbatim, ignoring the -gateway suffix. This causes Gateway Deployment/Service/Secret to collide with agent resources. Fix: use omit to strip nameOverride from gateway config dict, so the helper always uses the else branch: --gateway. Repro before fix: agents.kiro.nameOverride: my-bot → both agent AND gateway = my-bot After fix: agent = my-bot, gateway = openab-kiro-gateway --- charts/openab/templates/gateway-secret.yaml | 3 ++- charts/openab/templates/gateway.yaml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/charts/openab/templates/gateway-secret.yaml b/charts/openab/templates/gateway-secret.yaml index 5b2c26fc..7e24cda4 100644 --- a/charts/openab/templates/gateway-secret.yaml +++ b/charts/openab/templates/gateway-secret.yaml @@ -1,6 +1,7 @@ {{- range $name, $cfg := .Values.agents }} {{- if and (ne (include "openab.agentEnabled" $cfg) "false") ($cfg.gateway).enabled }} -{{- $d := dict "ctx" $ "agent" (printf "%s-gateway" $name) "cfg" $cfg }} +{{- $gwCfg := omit $cfg "nameOverride" }} +{{- $d := dict "ctx" $ "agent" (printf "%s-gateway" $name) "cfg" $gwCfg }} {{- $hasToken := ($cfg.gateway).token }} {{- $hasTeams := and (($cfg.gateway).teams).appId (($cfg.gateway).teams).appSecret }} {{- if or $hasToken $hasTeams }} diff --git a/charts/openab/templates/gateway.yaml b/charts/openab/templates/gateway.yaml index 7a9e5ba8..9639a49c 100644 --- a/charts/openab/templates/gateway.yaml +++ b/charts/openab/templates/gateway.yaml @@ -1,6 +1,7 @@ {{- range $name, $cfg := .Values.agents }} {{- if and (ne (include "openab.agentEnabled" $cfg) "false") ($cfg.gateway).enabled }} -{{- $d := dict "ctx" $ "agent" (printf "%s-gateway" $name) "cfg" $cfg }} +{{- $gwCfg := omit $cfg "nameOverride" }} +{{- $d := dict "ctx" $ "agent" (printf "%s-gateway" $name) "cfg" $gwCfg }} {{- $hasTeams := and (($cfg.gateway).teams).appId (($cfg.gateway).teams).appSecret }} --- apiVersion: apps/v1 From 61d2902f81ed5bc178c264553d3239c40ac68c8e Mon Sep 17 00:00:00 2001 From: masami-agent Date: Fri, 1 May 2026 14:36:20 +0000 Subject: [PATCH 4/6] fix(helm): make RUST_LOG configurable for gateway container Add gateway.rustLog value (default: "info"). Allows operators to set debug logging without editing templates. --- charts/openab/templates/gateway.yaml | 2 +- charts/openab/values.yaml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/charts/openab/templates/gateway.yaml b/charts/openab/templates/gateway.yaml index 9639a49c..ea7f0563 100644 --- a/charts/openab/templates/gateway.yaml +++ b/charts/openab/templates/gateway.yaml @@ -74,7 +74,7 @@ spec: {{- end }} {{- end }} - name: RUST_LOG - value: "info" + value: {{ ($cfg.gateway).rustLog | default "info" | quote }} livenessProbe: httpGet: path: /health diff --git a/charts/openab/values.yaml b/charts/openab/values.yaml index 0bb60696..0ea516f8 100644 --- a/charts/openab/values.yaml +++ b/charts/openab/values.yaml @@ -203,6 +203,7 @@ agents: tag: "" # defaults to Chart.AppVersion strategy: "Recreate" # Recreate (default, preserves WS connections) or RollingUpdate resources: {} # e.g. { requests: { cpu: 50m, memory: 64Mi }, limits: { memory: 128Mi } } + rustLog: "info" # RUST_LOG for gateway container (e.g. "openab_gateway=debug") # MS Teams adapter config (gateway-side env vars) # See docs/msteams-enterprise.md for full setup guide teams: From 451c679aa5604d1da2d2a64f55a0130cb5fa1392 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B6=85=E6=B8=A1=E6=B3=95=E5=B8=AB?= Date: Fri, 1 May 2026 14:52:12 +0000 Subject: [PATCH 5/6] =?UTF-8?q?fix(helm):=20remove=20gateway-ws-token=20du?= =?UTF-8?q?plication=20=E2=80=94=20single=20source=20of=20truth?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - gateway Deployment reads GATEWAY_WS_TOKEN from agent Secret instead of gateway Secret (eliminates token drift risk during rotation) - gateway-secret.yaml now only contains teams-app-secret - Fix strategy comment: Recreate prevents concurrent WS conflicts - Add --set-literal reminder for appSecret in values.yaml Co-authored-by: Four-Monk Review Team --- charts/openab/templates/gateway-secret.yaml | 8 +------- charts/openab/templates/gateway.yaml | 3 ++- charts/openab/values.yaml | 4 ++-- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/charts/openab/templates/gateway-secret.yaml b/charts/openab/templates/gateway-secret.yaml index 7e24cda4..f70de93b 100644 --- a/charts/openab/templates/gateway-secret.yaml +++ b/charts/openab/templates/gateway-secret.yaml @@ -2,9 +2,8 @@ {{- if and (ne (include "openab.agentEnabled" $cfg) "false") ($cfg.gateway).enabled }} {{- $gwCfg := omit $cfg "nameOverride" }} {{- $d := dict "ctx" $ "agent" (printf "%s-gateway" $name) "cfg" $gwCfg }} -{{- $hasToken := ($cfg.gateway).token }} {{- $hasTeams := and (($cfg.gateway).teams).appId (($cfg.gateway).teams).appSecret }} -{{- if or $hasToken $hasTeams }} +{{- if $hasTeams }} --- apiVersion: v1 kind: Secret @@ -16,12 +15,7 @@ metadata: "helm.sh/resource-policy": keep type: Opaque data: - {{- if $hasToken }} - gateway-ws-token: {{ $cfg.gateway.token | b64enc | quote }} - {{- end }} - {{- if $hasTeams }} teams-app-secret: {{ ($cfg.gateway).teams.appSecret | b64enc | quote }} - {{- end }} {{- end }} {{- end }} {{- end }} diff --git a/charts/openab/templates/gateway.yaml b/charts/openab/templates/gateway.yaml index ea7f0563..c33a13cd 100644 --- a/charts/openab/templates/gateway.yaml +++ b/charts/openab/templates/gateway.yaml @@ -42,10 +42,11 @@ spec: protocol: TCP env: {{- if ($cfg.gateway).token }} + {{- $agentD := dict "ctx" $ "agent" $name "cfg" $cfg }} - name: GATEWAY_WS_TOKEN valueFrom: secretKeyRef: - name: {{ include "openab.agentFullname" $d }} + name: {{ include "openab.agentFullname" $agentD }} key: gateway-ws-token {{- end }} {{- if $hasTeams }} diff --git a/charts/openab/values.yaml b/charts/openab/values.yaml index 0ea516f8..0eddf16e 100644 --- a/charts/openab/values.yaml +++ b/charts/openab/values.yaml @@ -201,14 +201,14 @@ agents: botUsername: "" # optional, for @mention gating image: "ghcr.io/openabdev/openab-gateway" # gateway container image tag: "" # defaults to Chart.AppVersion - strategy: "Recreate" # Recreate (default, preserves WS connections) or RollingUpdate + strategy: "Recreate" # Recreate (default, prevents concurrent WS conflicts) or RollingUpdate resources: {} # e.g. { requests: { cpu: 50m, memory: 64Mi }, limits: { memory: 128Mi } } rustLog: "info" # RUST_LOG for gateway container (e.g. "openab_gateway=debug") # MS Teams adapter config (gateway-side env vars) # See docs/msteams-enterprise.md for full setup guide teams: appId: "" # Azure Entra ID application (client) ID → TEAMS_APP_ID - appSecret: "" # Azure Entra ID client secret → TEAMS_APP_SECRET + appSecret: "" # Azure Entra ID client secret → TEAMS_APP_SECRET (use --set-literal or external secret mgmt) # ⚠️ Required for Single Tenant bots — use tenant-specific endpoint oauthEndpoint: "" # → TEAMS_OAUTH_ENDPOINT openidMetadata: "" # Override for sovereign clouds → TEAMS_OPENID_METADATA From 8a8f23ef73a2a3600c1061acc4bf197977ef16c6 Mon Sep 17 00:00:00 2001 From: masami-agent Date: Fri, 1 May 2026 14:53:10 +0000 Subject: [PATCH 6/6] fix(helm): eliminate gateway-ws-token duplication across Secrets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GATEWAY_WS_TOKEN was stored in both agent Secret and gateway Secret. Fix: gateway reads GATEWAY_WS_TOKEN from agent's Secret (single source of truth). Gateway Secret now only contains teams-app-secret. Before: token in 2 Secrets → rotation risk After: token in 1 Secret → single source of truth --- charts/openab/templates/gateway.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/charts/openab/templates/gateway.yaml b/charts/openab/templates/gateway.yaml index c33a13cd..39672c05 100644 --- a/charts/openab/templates/gateway.yaml +++ b/charts/openab/templates/gateway.yaml @@ -2,6 +2,7 @@ {{- if and (ne (include "openab.agentEnabled" $cfg) "false") ($cfg.gateway).enabled }} {{- $gwCfg := omit $cfg "nameOverride" }} {{- $d := dict "ctx" $ "agent" (printf "%s-gateway" $name) "cfg" $gwCfg }} +{{- $agentD := dict "ctx" $ "agent" $name "cfg" $cfg }} {{- $hasTeams := and (($cfg.gateway).teams).appId (($cfg.gateway).teams).appSecret }} --- apiVersion: apps/v1