Skip to main content

Release 0.5.0 — Enterprise RBAC and OpenFGA Authorization

Released: 2026-05-26 Chart: oci://ghcr.io/cnoe-io/charts/ai-platform-engineering:0.5.0 Previous release: 0.4.18

Highlights

0.5.0 is a headline minor release that lands CAIPE's enterprise authorization foundation: a full cutover from legacy role-based access control to relationship-based access control (ReBAC) backed by OpenFGA, with Keycloak as the identity provider and an AgentGateway ext_authz bridge enforcing per-call MCP decisions. The release introduces a new Webex bot alongside ReBAC-aware Slack routing, an envelope-encrypted credential store and OAuth connector platform, and a hardened secrets bootstrap that fails loudly on dev placeholders instead of silently shipping insecure defaults. The entire authorization stack is opt-in and disabled by default — for a stock 0.4.18 deployment this is a drop-in upgrade with no values.yaml edits required. Operators who adopt RBAC get team-based access control, per-document RAG ACLs, channel-derived team binding for bots, and a redesigned admin UI for managing teams, identity-group sync, and onboarding defaults.

What's New

Identity & Authorization (OpenFGA ReBAC)

  • OpenFGA ReBAC core, admin BFF, and admin UI — new ui/src/lib/rbac library (OpenFGA client, tuple builder, store, PDP, decision cache, role-mapping, group-sync, team/agent resolvers, Keycloak Admin REST helpers), the full admin BFF API surface, and admin UI components for teams and authorization management (#1526)
  • Auth foundation Helm charts — brand-new keycloak, openfga, openfga-authz-bridge, and agentgateway subcharts, including Keycloak realm init, token-exchange and auth-reconcile jobs, the OpenFGA authorization model bootstrap, and the Python ext_authz bridge (#1496)
  • Shared MCP agent-auth library — new mcp-agent-auth package (JWT validation, caller-key derivation, OBO exchange, in-process JWKS cache, downstream token forwarder, PDP) wired uniformly into 13 agent MCP servers via MCPAuthMiddleware (Spec 101) (#1524)
  • RAG ReBAC with per-document ACLs — OpenFGA-backed authorization for the RAG server, ACL propagation through every ingestor, per-document enforcement at retrieval time, and a userinfo cache for the OBO-validation hot path (#1525)
  • admin implies member + auto-provisioned Super Admins team — OpenFGA model bump so anyone with the admin relation on a team satisfies team#member checks, removing the need to dual-write tuples; a Super Admins team is auto-provisioned for platform defaults (#1555)
  • Persisted onboarding defaults — default team and agent for new users stored in platform_config and editable from the admin UI/BFF (#1558)
  • Admin-configurable discovery cache TTL — tune the Slack/Webex onboarding discovery cache from the admin UI (#1556)

Bots: Webex + Slack ReBAC

  • New Webex bot integration — full webex_bot integration (a2a client, app, identity linking, audit, hardening, Prometheus metrics) plus a webex-bot Helm subchart, Dockerfile, and CI workflow (#1523)
  • Slack ReBAC additions — channel-team resolver, JIT identity linking, SSE OBO, runtime policy, and opt-in first-message channel onboarding for unmapped channels (#1523)
  • Channel-derived team binding — replaces the single-team active_team JWT claim with a model that derives the authorizing team from the channel/context (Slack channel, Webex space, DM), correct for multi-team users by construction; adds personal DM commands across both bots (#1562)

Connections & Credentials

  • Envelope-encrypted credential store + OAuth platform — MongoDB-backed envelope-encrypted credential storage with KMS-style data-key wrapping (AES-GCM with a master key), an OAuth connector platform (built-in providers, token refresh, state store, provider detection), and a Python credential-exchange client for agents; gated behind the CAIPE_CREDENTIALS_ENABLED feature flag and disabled by default (#1497)

Dynamic Agents

  • JWT/OBO auth + OpenFGA PDP gate — JWKS validation middleware, on-behalf-of token exchange, request-local token context, and a ReBAC PDP gate bring the dynamic-agents runtime to parity with the rest of the auth surface (#1499)
  • MCP endpoint normalizer + self-heal — canonicalizes MCP URLs from bot configs (trailing slash, /mcp suffix, scheme inference), forwards request tokens via OBO, resolves credential refs, and adds probe + self-heal diagnostics (#1499)
  • Editor blocker hints + protected platform default agent — surfaces blocker hints in the agent editor and prevents deletion/misconfiguration of the platform default agent (#1559)

Supervisor

  • get_file_line_count tool — new tool the agent is prompted to call before read_file, so it reads large files in bounded ranges instead of pulling entire files into context (#1565)
  • User identity + JWT forwarding — opt-in ENABLE_USER_INFO_TOOL captures user identity from the JWT (enabling the user_info tool and JWT context middleware); FORWARD_JWT_TO_MCP forwards the user JWT as a Bearer token to HTTP/streamable-HTTP MCP connections. Both default to false (#1524)

Setup

  • Expanded embeddings menusetup-caipe.sh now offers all 7 EmbeddingsFactory providers, including AWS Bedrock, Cohere, and Voyage AI (the recommended embeddings provider for Anthropic Claude users) (#1538)

Bug Fixes

  • rbac: scoped team admins can now edit, delete, and configure their own team — previously group admins could not modify anything within their own group (issue #1509, fixed in #1567)
  • ui/slack: drop stale env-provided Slack default agent/team and surface a warning instead of silently honoring removed defaults (#1539)
  • ui: use users.conversations for Slack channel discovery to dodge Slack API rate limits (#1536)
  • chart/caipe-ui: include workflow_configs in the app configmap so self-service workflows render correctly (#1549)
  • setup-caipe: pull the Ollama embedding model during setup so local embeddings work out of the box (#1553)

Security

This release is security-heavy by design — it ships the authorization stack and hardens the secrets bootstrap.

  • Keycloak client-secret hardening — adds a reconcile pass that rotates dev placeholder secrets for the three confidential service-account clients (caipe-platform, caipe-slack-bot, caipe-webex-bot) on every install/upgrade, a strict-mode gate (keycloak.strictClientSecrets, default off) that fails the install if any known dev placeholder still mints a token, ExternalSecrets support for caipe-platform.OIDC_CLIENT_SECRET, and removal of 5 demo users with hardcoded passwords from the bundled realm config (#1518)
  • Kill BFF admin/admin fallback + strict-mode gates — the BFF Keycloak Admin client no longer falls back to admin/admin against /realms/master; production requires the client_credentials path against a confidential client and fails loudly otherwise. Adds MongoDB and NextAuth strict-mode gates, and auto-wires KEYCLOAK_ADMIN_CLIENT_ID/SECRET from the same Secret the Keycloak chart writes (R1/R3/R4 of the May 2026 secrets audit) (#1519)
  • Envelope-encrypted credentials — credentials are stored with AES-GCM envelope encryption and KMS-style data-key wrapping; production installs must use aws-kms (the local-cmk provider is for non-production testing only) (#1497)
  • MongoDB strict-password gate — new mongodb.auth.strictPasswords (default off) makes helm install/upgrade fail-fast when auth.rootPassword is left at a known placeholder such as changeme
  • Dependency hardening — pin aiohttp, websockets, and @aws-sdk/client-kms to exact versions; bump fastmcp to 3.3.1 and regenerate lock files; refresh stale MCP uv.lock files; remove fixable grype findings from container images; bump protobuf and qs

Breaking Changes

There are no breaking Helm values changes — every key in the chart diff is additive, and the entire RBAC/OpenFGA/Keycloak/Webex stack ships disabled by default (tags.keycloak, tags.webex-bot, openfga.enabled, global.agentgateway.enabled, CAIPE_CREDENTIALS_ENABLED all default to false). For a stock 0.4.18 deployment, 0.5.0 is a drop-in upgrade.

One behavioral breaking change applies only if you were tracking pre-release 0.5.x builds or had a custom integration that read the active_team JWT claim:

  • active_team JWT claim removed (#1562) — the single-team-per-token active_team claim and all of its supporting code (heal routes, scope matrices, diagnostic invariants, env passthrough, cleanup script, team-scope Keycloak helpers) have been demolished and replaced with channel-derived team binding. Consequence if not updated: any external code that inspected active_team on a CAIPE-issued JWT will no longer find the claim. Authorization is now derived from the channel/space/DM context of the request. No action is required for operators upgrading from 0.4.18, since that release never issued the claim through this stack.

Known Issues

None known at this time.

Upgrade

helm upgrade ai-platform-engineering \
oci://ghcr.io/cnoe-io/charts/ai-platform-engineering \
--version 0.5.0 \
-f your-values.yaml

Upgrade Guide: 0.4.18 → 0.5.0

Overview

0.5.0 introduces the enterprise authorization foundation — OpenFGA ReBAC, Keycloak identity, AgentGateway ext_authz, a Webex bot, and an envelope-encrypted credential store. Despite the size of the release (112 commits), the upgrade is drop-in for existing 0.4.18 deployments: every new Helm value is additive with a working default, and all of the new authorization machinery is gated behind feature flags that default to disabled. You only need to edit values.yaml if you are opting into RBAC, the Webex bot, or the credential store.

Helm Values Changes

No keys were renamed, removed, or type-changed between 0.4.18 and 0.5.0. The only modified line is a comment reformat of the unchanged mongodb.auth.rootPassword: "changeme" default. Everything else is new optional configuration.

Breaking Changes

None. No breaking Helm values changes.

New Optional Fields

Chart toggles & global config

KeyDefaultDescription
tags.webex-botfalseEnable the new Webex bot subchart
tags.keycloakfalseEnable the bundled Keycloak identity provider
openfga.enabledfalseEnable the OpenFGA relationship PDP
openfgaAuthzBridge.enabledfalseEnable the AgentGateway ext_authz bridge
global.image.channel"" (auto)Force the image repo channel (pre-release or release); empty auto-selects by appVersion
global.agentgateway.enabledfalseRoute MCP traffic through the AgentGateway proxy
global.agentgateway.installIstioCrdsfalseInstall Istio CRDs (leave false if Istio is already present)
global.agentgateway.proxyPort8080AgentGateway proxy listener port
global.agentgateway.extAuth.*disabledext_authz service name/namespace/port for OpenFGA decisions
global.openfga.httpUrlhttp://{{ .Release.Name }}-openfga:8080OpenFGA discovery URL for CAIPE components
global.openfga.storeNamecaipe-openfgaOpenFGA store name
agentgateway.* (top level)enabled: falseAgentGateway proxy image/config
<agent>.mcp.agentgateway.enabledfalsePer-agent: route MCP calls through AgentGateway (with protocol: StreamableHTTP)

Supervisor (global.config)

Env VarDefaultDescription
ENABLE_USER_INFO_TOOLfalseCapture user identity from the JWT; enables the user_info tool and JWT context middleware
FORWARD_JWT_TO_MCPfalseForward the user JWT as a Bearer token to HTTP/streamable-HTTP MCP connections (requires ENABLE_USER_INFO_TOOL=true)

CAIPE UI (caipe-ui.config / caipe-ui.keycloakAdminClient)

KeyDefaultDescription
keycloakAdminClient.secretNamecaipe-platform-secretSecret holding the Keycloak Admin REST client secret
keycloakAdminClient.secretKeyOIDC_CLIENT_SECRETKey within that Secret
keycloakAdminClient.clientIdcaipe-platformKeycloak Admin REST client ID
CAIPE_CREDENTIALS_ENABLEDfalseEnable the Connections & Secrets credential store
CREDENTIAL_STORE_BACKENDmongodb-envelopeCredential storage backend
CREDENTIAL_KEY_PROVIDERlocal-cmkData-key provider (local-cmk for test, aws-kms for prod)
CREDENTIAL_KMS_CMK_ID / CREDENTIAL_KMS_REGION""AWS KMS CMK id/region when using aws-kms
CREDENTIAL_BOOTSTRAP_OAUTH_CONNECTORSfalseBootstrap global OAuth connectors from server env at startup
OPENFGA_HTTP""OpenFGA URL for relationship authorization (set after OpenFGA is installed)
OPENFGA_STORE_NAMEcaipe-openfgaOpenFGA store name
OPENFGA_RECONCILE_ENABLEDfalseEnable OpenFGA reconciliation
KEYCLOAK_URL / KEYCLOAK_REALM"" / caipeKeycloak Admin API integration
KEYCLOAK_RESOURCE_SERVER_IDcaipe-platformKeycloak resource server id for resource/scope sync
SLACK_WORKSPACE_ALIASCAIPECanonical Slack workspace namespace for ReBAC/routes
SLACK_BOT_ADMIN_URL / SLACK_BOT_ADMIN_AUDIENCEslack-bot URL / caipe-slack-bot-adminSlack bot internal admin API used by the BFF
WEBEX_BOT_ADMIN_URL / WEBEX_BOT_ADMIN_AUDIENCEwebex-bot URL / caipe-webex-bot-adminWebex bot internal admin API
WEBEX_THREAD_CONTEXT_*true / 10 / 4000Webex thread-context window settings
CAIPE_ORG_KEY / CAIPE_ORG_DISPLAY_NAMEcaipe / CAIPEOrg namespace + display name

Dynamic Agents (dynamic-agents.config)

Env VarDefaultDescription
KEYCLOAK_URLhttp://ai-platform-engineering-keycloak:8080In-cluster Keycloak service URL for JWKS fetch (override for external IdP)
OIDC_ISSUER""Browser-facing issuer baked into JWTs; falls back to deriving from KEYCLOAK_URL in dev
CAIPE_CREDENTIALS_ENABLEDfalseEnable the credential-exchange client
CREDENTIAL_API_URLcaipe-ui /api/credentialsCredential exchange API endpoint
USE_IMPERSONATION_TOKENSfalseUse impersonation tokens for downstream calls
AGENT_GATEWAY_MCP_SERVER_IDSjiraMCP server IDs routed through the AgentGateway backend

Slack bot (slack-bot.config)

Env VarDefaultDescription
SLACK_WORKSPACE_ALIASCAIPECanonical workspace namespace for ReBAC/routes
SLACK_AGENT_ROUTES_MODEdb_preferPrefer UI-managed Slack routes, fall back to static config
SLACK_AUTO_ASSIGN_UNMAPPED_CHANNELSfalseOpt-in first-message channel onboarding
SLACK_DEFAULT_TEAM_SLUG / SLACK_DEFAULT_AGENT_ID""Required when auto-assignment is enabled
SLACK_ADMIN_API_ENABLEDfalseInternal admin API for route status/reload/config sync
SLACK_ADMIN_JWT_ISSUER / SLACK_ADMIN_JWT_AUDIENCE"" / caipe-slack-bot-adminOIDC issuer/audience for the admin API
SLACK_ADMIN_ALLOWED_CLIENT_IDScaipe-uiClient IDs allowed to call the admin API

New subcharts (entirely new value blocks)

BlockEnabled byPurpose
webex-bottags.webex-bot=trueWebex spaces, identity linking, OpenFGA ReBAC
keycloaktags.keycloak=trueIdentity provider, federation broker, RFC 8693 token exchange
openfgaopenfga.enabled=trueRelationship PDP (team/resource tuples)
openfga-authz-bridgeopenfgaAuthzBridge.enabled=trueEnvoy ext_authz → OpenFGA Check bridge for AgentGateway

Deprecated / Removed Keys

None. No keys were deprecated or removed in 0.5.0.

Data Migrations

  • MongoDB: no destructive schema migration. New collections back the credential store (envelope-encrypted) and Slack/Webex route management; the credential store also adds indexes via scripts/init-credential-mongo-indexes.ts. These are created lazily/on-demand and only when the corresponding feature is enabled.
  • OpenFGA: if you enable RBAC, the OpenFGA chart bootstraps the authorization model (authorization-model.json) and creates the caipe-openfga store. Existing deployments have nothing to migrate — there was no prior OpenFGA store.
  • Keycloak: the Keycloak subchart is new in this release. Enabling it initializes the caipe realm, token-exchange clients, and (optionally) the upstream IdP broker. No migration from a prior CAIPE-managed Keycloak is required for 0.4.18 upgraders.
  • active_team JWT claim: no data migration — the claim is simply no longer issued, and authorization is derived from channel context at request time.

Upgrade Runbook

1. Update chart version

helm upgrade ai-platform-engineering \
oci://ghcr.io/cnoe-io/charts/ai-platform-engineering \
--version 0.5.0 \
-f your-values.yaml

This alone is sufficient for a stock upgrade — the new authorization stack stays disabled.

2. Apply values.yaml changes

No breaking changes require edits. If you want to opt into RBAC, enable the foundation subcharts and point CAIPE UI at them:

tags:
keycloak: true

openfga:
enabled: true

caipe-ui:
config:
OPENFGA_HTTP: "http://ai-platform-engineering-openfga:8080"
OPENFGA_RECONCILE_ENABLED: "true"
KEYCLOAK_URL: "http://ai-platform-engineering-keycloak:8080"

To opt into the Webex bot:

tags:
webex-bot: true

To opt into the credential store (use aws-kms in production):

caipe-ui:
config:
CAIPE_CREDENTIALS_ENABLED: "true"
CREDENTIAL_KEY_PROVIDER: "aws-kms"
CREDENTIAL_KMS_CMK_ID: "<your-cmk-id>"
CREDENTIAL_KMS_REGION: "<your-region>"

For production secrets hygiene, consider turning on the new strict-mode gates once you have wired real secrets:

mongodb:
auth:
strictPasswords: true # fail-fast on placeholder rootPassword

3. Verify

kubectl get pods -n <namespace>

# If you enabled RBAC, confirm the auth foundation pods are healthy
kubectl get pods -n <namespace> | grep -E 'keycloak|openfga'

# If you enabled the Webex bot
kubectl get deploy -n <namespace> | grep webex-bot

For a stock upgrade, confirm all existing pods roll cleanly — no new admission constraints are introduced.

Full Values Diff

Raw diff (0.4.18 → 0.5.0)
--- /tmp/vf-0.5.0.yaml	2026-05-29 09:11:41
+++ /tmp/vt-0.5.0.yaml 2026-05-29 09:11:42
@@ -22,6 +22,8 @@
agent-petstore: false
rag-stack: false
slack-bot: false
+ webex-bot: false
+ keycloak: false

# Global configuration shared across all subcharts
global:
@@ -30,6 +32,11 @@
# Individual subchart `image.tag` values still take highest precedence.
image:
tag: ""
+ # -- Image repository channel for maintained CAIPE images.
+ # Empty means auto: rc/hotfix/dev chart appVersions use `pre-release/`,
+ # final release appVersions use the root published image repositories.
+ # Set to `pre-release` or `release` to force either repository channel.
+ channel: ""

# Deployment mode: "single-node" (all agents in-process) or "multi-node" (each agent as a separate pod)
deploymentMode: "multi-node"
@@ -115,7 +122,30 @@

agentgateway:
enabled: false
+ # Set to true only if Istio CRDs are NOT already present in the cluster.
+ # If Istio is already installed (any version), leave this false to avoid conflicts.
+ installIstioCrds: false
+ # Port for the agentgateway proxy listener (Gateway resource)
+ proxyPort: 8080
+ extAuth:
+ enabled: false
+ serviceName: "ai-platform-engineering-openfga-authz-bridge"
+ serviceNamespace: ""
+ port: 9100

+ # OpenFGA service discovery defaults for CAIPE components that perform
+ # relationship-based authorization or reconciliation.
+ openfga:
+ httpUrl: "http://{{ .Release.Name }}-openfga:8080"
+ storeName: "caipe-openfga"
+
+agentgateway:
+ enabled: false
+ image:
+ repository: cr.agentgateway.dev/agentgateway
+ tag: v1.1.0
+ pullPolicy: IfNotPresent
+
# LangGraph Redis for checkpoint and cross-thread store persistence.
# Two deployment options:
# 1. Dedicated Redis Stack (recommended): set enabled=true to deploy langgraph-redis subchart
@@ -276,6 +306,8 @@
USE_STRUCTURED_RESPONSE: "true" # Set to "true" to enforce agent to always use structured response format as the final output
TASK_CONFIG_PATH: "/app/task_config.yaml"
POLICY_FILE_PATH: "/app/policy.lp"
+ ENABLE_USER_INFO_TOOL: "false" # Capture user identity from JWT; enables user_info tool and JWT context middleware
+ FORWARD_JWT_TO_MCP: "false" # Forward the user JWT as Bearer token to HTTP/streamable-HTTP MCP connections (requires ENABLE_USER_INFO_TOOL=true). Also used by sub-agents via base_langgraph_agent.
# Self-service workflow env vars — referenced as ${VAR_NAME} in task_config.yaml prompts.
# Set these per environment so system workflows can resolve repo references at runtime.
# JARVIS_WORKFLOWS_REPO: "org/jarvis-workflows" # Templates repo (safe-settings, terraform, etc.)
@@ -377,6 +409,12 @@
pullPolicy: "IfNotPresent"
mode: "http" # Options: stdio, http
port: 8000
+ # Route MCP traffic through agentgateway proxy (requires global.agentgateway.enabled).
+ # When enabled, subagent MCP calls go through the agentgateway proxy which can
+ # enforce JWT validation and ext_authz decisions backed by OpenFGA.
+ agentgateway:
+ enabled: false
+ protocol: StreamableHTTP # SSE or StreamableHTTP

agent-backstage:
nameOverride: "agent-backstage"
@@ -391,6 +429,9 @@
pullPolicy: "IfNotPresent"
mode: "http" # Options: stdio, http
port: 8000
+ agentgateway:
+ enabled: false
+ protocol: StreamableHTTP

agent-confluence:
nameOverride: "agent-confluence"
@@ -404,6 +445,9 @@
pullPolicy: "IfNotPresent"
mode: "http" # Options: stdio, http
port: 8000
+ agentgateway:
+ enabled: false
+ protocol: StreamableHTTP
env:
TRANSPORT: "streamable-http"

@@ -478,6 +522,9 @@
pullPolicy: "IfNotPresent"
mode: "http" # Options: stdio, http
port: 8000
+ agentgateway:
+ enabled: false
+ protocol: StreamableHTTP

agent-pagerduty:
nameOverride: "agent-pagerduty"
@@ -492,6 +539,9 @@
pullPolicy: "IfNotPresent"
mode: "http" # Options: stdio, http
port: 8000
+ agentgateway:
+ enabled: false
+ protocol: StreamableHTTP

agent-slack:
nameOverride: "agent-slack"
@@ -505,6 +555,9 @@
pullPolicy: "IfNotPresent"
mode: "http" # Options: stdio, http
port: 3001
+ agentgateway:
+ enabled: false
+ protocol: StreamableHTTP
command: ["--transport", "http"]
env:
SLACK_MCP_HOST: "0.0.0.0"
@@ -526,6 +579,9 @@
pullPolicy: "IfNotPresent"
mode: "http" # Options: stdio, http
port: 8000
+ agentgateway:
+ enabled: false
+ protocol: StreamableHTTP
env:
# -- Block kubectl get/describe secret(s) and redact Secret data from output. Defaults to true (on).
RESTRICT_KUBECTL_SECRETS: "true"
@@ -553,6 +609,9 @@
pullPolicy: "IfNotPresent"
mode: "http" # Options: stdio, http
port: 8000
+ agentgateway:
+ enabled: false
+ protocol: StreamableHTTP

agent-victorops:
nameOverride: "agent-victorops"
@@ -566,6 +625,9 @@
pullPolicy: "IfNotPresent"
mode: "http" # Options: stdio, http
port: 8000
+ agentgateway:
+ enabled: false
+ protocol: StreamableHTTP

agent-webex:
nameOverride: "agent-webex"
@@ -580,6 +642,9 @@
pullPolicy: "IfNotPresent"
mode: "http" # Options: stdio, http
port: 8000
+ agentgateway:
+ enabled: false
+ protocol: StreamableHTTP

agent-weather:
nameOverride: "agent-weather"
@@ -608,6 +673,9 @@
pullPolicy: "IfNotPresent"
mode: "http" # Options: stdio, http
port: 8000
+ agentgateway:
+ enabled: false
+ protocol: StreamableHTTP

agent-netutils:
nameOverride: "agent-netutils"
@@ -624,6 +692,9 @@
pullPolicy: "IfNotPresent"
mode: "http" # Options: stdio, http
port: 8000
+ agentgateway:
+ enabled: false
+ protocol: StreamableHTTP

agent-weather:
nameOverride: "agent-weather"
@@ -650,6 +721,25 @@
skills:
enabled: true
nameOverride: "caipe-ui"
+ # R1 upstream fix (May 2026): default the Keycloak Admin REST client
+ # secret name to "caipe-platform-secret" — the conventional name an
+ # operator passes via `keycloak.platformClient.secretRef` AND the
+ # default target of the keycloak chart's ExternalSecret (see below
+ # where we also default `keycloak.platformClient.secretRef` itself).
+ #
+ # Helm does not support cross-subchart value substitution at template
+ # time, so we have to hardcode the conventional name in both places.
+ # Operators using a non-default Secret name must override BOTH:
+ # keycloak.platformClient.secretRef: my-custom-platform-secret
+ # caipe-ui.keycloakAdminClient.secretName: my-custom-platform-secret
+ #
+ # See docs/docs/security/rbac/secrets-bootstrap.md section "R1: BFF
+ # Keycloak Admin token — production-safety gate".
+ # assisted-by Claude:claude-opus-4-7
+ keycloakAdminClient:
+ secretName: "caipe-platform-secret"
+ secretKey: "OIDC_CLIENT_SECRET"
+ clientId: "caipe-platform"
image:
repository: "ghcr.io/cnoe-io/caipe-ui"
# tag defaults to .Chart.AppVersion when not specified
@@ -719,6 +809,18 @@
DYNAMIC_AGENTS_ENABLED: "false"
# Dynamic Agents service URL (only used when DYNAMIC_AGENTS_ENABLED is "true")
# DYNAMIC_AGENTS_URL: "http://ai-platform-engineering-dynamic-agents:8001"
+ # Connections & Secrets credential store. Disabled by default. Use local-cmk
+ # only for non-production testing; production must use aws-kms.
+ CAIPE_CREDENTIALS_ENABLED: "false"
+ CREDENTIAL_STORE_BACKEND: "mongodb-envelope"
+ CREDENTIAL_KEY_PROVIDER: "local-cmk"
+ CREDENTIAL_KMS_CMK_ID: ""
+ CREDENTIAL_KMS_REGION: ""
+ CREDENTIAL_SERVICE_AUDIENCE: "caipe-credential-service"
+ # Bootstrap global OAuth connectors from server env at startup. In
+ # Kubernetes, provide provider client IDs/secrets/redirect URIs through
+ # externalSecrets; in Docker Compose, provide them through .env.
+ CREDENTIAL_BOOTSTRAP_OAUTH_CONNECTORS: "false"
# Standalone skill-scanner microservice (cisco-ai-defense/skill-scanner).
# Active when global.skillScanner.enabled=true; the in-cluster Service
# name is derived from the Helm release name, so the URL is rendered
@@ -729,6 +831,15 @@
SKILL_SCANNER_URL: "http://{{ .Release.Name }}-skill-scanner:8000"
# MongoDB configuration
MONGODB_DATABASE: "caipe"
+ # OpenFGA relationship authorization. Enable reconciliation only after
+ # OpenFGA is installed and the authorization model has been initialized.
+ OPENFGA_HTTP: ""
+ OPENFGA_STORE_NAME: "caipe-openfga"
+ OPENFGA_RECONCILE_ENABLED: "false"
+ # Keycloak Admin API integration for resource/scope synchronization.
+ KEYCLOAK_URL: ""
+ KEYCLOAK_REALM: "caipe"
+ KEYCLOAK_RESOURCE_SERVER_ID: "caipe-platform"
# NextAuth URL (non-sensitive)
NEXTAUTH_URL: "http://localhost:3000"
# Node environment
@@ -737,6 +848,29 @@
TAGLINE: "Multi-Agent Workflow Automation"
DESCRIPTION: "Where Humans and AI agents collaborate to deliver high quality outcomes."
APP_NAME: "CAIPE"
+ # Canonical Slack workspace namespace used by UI-managed Slack ReBAC/routes.
+ SLACK_WORKSPACE_ALIAS: "CAIPE"
+ # Slack bot internal admin API used by the Web UI BFF for route reload and
+ # one-time static-config-to-MongoDB/OpenFGA migration. The BFF uses the
+ # existing OIDC_CLIENT_ID/OIDC_CLIENT_SECRET Keycloak client credentials.
+ SLACK_BOT_ADMIN_URL: "http://ai-platform-engineering-slack-bot:3001"
+ SLACK_BOT_ADMIN_AUDIENCE: "caipe-slack-bot-admin"
+ # SLACK_BOT_ADMIN_TOKEN_URL: "http://keycloak:7080/realms/caipe/protocol/openid-connect/token"
+ # SLACK_BOT_ADMIN_SCOPE: "slack:routes:read slack:routes:reload slack:routes:sync"
+ SLACK_DEFAULT_TEAM_SLUG: ""
+ SLACK_DEFAULT_AGENT_ID: ""
+ # Webex bot internal admin API (BFF access-check + route management).
+ WEBEX_BOT_ADMIN_URL: "http://ai-platform-engineering-webex-bot:3002"
+ WEBEX_BOT_ADMIN_CLIENT_ID: "caipe-ui"
+ WEBEX_BOT_ADMIN_AUDIENCE: "caipe-webex-bot-admin"
+ # WEBEX_BOT_ADMIN_TOKEN_URL: "http://keycloak:7080/realms/caipe/protocol/openid-connect/token"
+ WEBEX_DEFAULT_TEAM_SLUG: ""
+ WEBEX_DEFAULT_AGENT_ID: ""
+ WEBEX_THREAD_CONTEXT_ENABLED: "true"
+ WEBEX_THREAD_CONTEXT_MAX_MESSAGES: "10"
+ WEBEX_THREAD_CONTEXT_MAX_CHARS: "4000"
+ CAIPE_ORG_KEY: "caipe"
+ CAIPE_ORG_DISPLAY_NAME: "CAIPE"
LOGO_URL: "/logo.svg"
LOGO_STYLE: "default"
# SPINNER_COLOR: ""
@@ -779,8 +913,18 @@
size: 10Gi
auth:
rootUsername: "admin"
- rootPassword: "changeme" # CHANGE THIS or use external secrets
+ # CHANGE THIS or use external secrets.
+ # R3 (May 2026): set `mongodb.strictPasswords: true` below to make
+ # `helm install` / `helm upgrade` fail-fast on the placeholder.
+ rootPassword: "changeme"
database: "caipe"
+ # R3: Production-safety gate. When true AND `externalSecrets.enabled`
+ # is false, the chart refuses to render if `auth.rootPassword` is a
+ # known placeholder ("changeme", "admin", "password", "mongo",
+ # "root", "test", etc.). Mirrors `keycloak.strictClientSecrets`.
+ # Default false so docker-compose dev + CI matrix keep working.
+ # assisted-by Claude:claude-opus-4-7
+ strictPasswords: false
# External Secrets for MongoDB credentials
externalSecrets:
enabled: false # Set to true to use external secrets
@@ -887,8 +1031,31 @@
port: 8001
# ConfigMap for non-sensitive configuration
config:
+ # ─── Keycloak / OIDC (REQUIRED for Bearer token validation) ─────────
+ # In-cluster Keycloak service URL used for the server-to-server JWKS
+ # fetch. The bundled Keycloak subchart exposes its service as
+ # `<release>-keycloak`; this default works for the umbrella chart
+ # but MUST be overridden when pointing dynamic-agents at an external
+ # Keycloak (production IdP / forge.dev / etc.).
+ KEYCLOAK_URL: "http://ai-platform-engineering-keycloak:8080"
+ # Browser-facing issuer string baked into JWTs (Keycloak's
+ # KC_HOSTNAME). Override when the public issuer differs from
+ # KEYCLOAK_URL (the typical production topology), e.g.
+ # OIDC_ISSUER: "https://idp.example.com/realms/caipe".
+ # Leaving this empty falls back to deriving the issuer from
+ # KEYCLOAK_URL, which only works in dev where both URLs coincide;
+ # NOTES.txt prints a warning otherwise.
+ OIDC_ISSUER: ""
# MongoDB configuration (uses same database as CAIPE UI)
MONGODB_DATABASE: "caipe"
+ # Connections & Secrets credential exchange client. Disabled by default.
+ CAIPE_CREDENTIALS_ENABLED: "false"
+ CREDENTIAL_API_URL: "http://ai-platform-engineering-caipe-ui:3000/api/credentials"
+ CREDENTIAL_SERVICE_AUDIENCE: "caipe-credential-service"
+ USE_IMPERSONATION_TOKENS: "false"
+ # MCP server IDs routed through the shared AgentGateway backend.
+ # Other MCP servers keep direct endpoints so tool names reflect real upstreams.
+ AGENT_GATEWAY_MCP_SERVER_IDS: "jira"
# LLM configuration (override if needed)
# LLM_PROVIDER: "openai"
# LLM_MODEL: "gpt-4o"
@@ -930,9 +1097,20 @@
SLACK_INTEGRATION_SILENCE_ENV: "false"
# MONGODB_URI: "" # Override per environment
# SLACK_WORKSPACE_URL: "" # e.g. "https://mycompany.slack.com"
+ SLACK_WORKSPACE_ALIAS: "CAIPE" # Canonical workspace namespace for Slack ReBAC/routes
# SLACK_INTEGRATION_ENABLE_AUTH: "true" # Enable OAuth2 Client Credentials
# OAUTH2_TOKEN_URL: "" # OIDC token endpoint
# OAUTH2_CLIENT_ID: "" # OAuth2 client ID
+ SLACK_AGENT_ROUTES_MODE: "db_prefer" # Prefer UI-managed Slack routes, fallback to static config
+ SLACK_AUTO_ASSIGN_UNMAPPED_CHANNELS: "false" # Opt-in first-message channel onboarding
+ SLACK_DEFAULT_TEAM_SLUG: "" # Required when auto-assignment is enabled
+ SLACK_DEFAULT_AGENT_ID: "" # Required when auto-assignment is enabled
+ SLACK_ADMIN_API_ENABLED: "false" # Internal admin API for route status/reload/config sync
+ SLACK_ADMIN_API_HOST: "0.0.0.0"
+ SLACK_ADMIN_API_PORT: "3001"
+ SLACK_ADMIN_JWT_ISSUER: "" # Set to Keycloak/OIDC issuer when admin API is enabled
+ SLACK_ADMIN_JWT_AUDIENCE: "caipe-slack-bot-admin"
+ SLACK_ADMIN_ALLOWED_CLIENT_IDS: "caipe-ui"

# -- Reference to a pre-existing Kubernetes Secret.
# Should contain: SLACK_BOT_TOKEN, SLACK_APP_TOKEN, SLACK_SIGNING_SECRET,
@@ -963,10 +1141,41 @@
name: "vault"
kind: "ClusterSecretStore"
data: []
+ # Example placeholders. Keep values in your external secret backend; these
+ # keys are materialized into the generated Kubernetes Secret and injected
+ # into the slack-bot pod via envFrom.
# - secretKey: SLACK_BOT_TOKEN
# remoteRef:
# key: prod/slack-bot
# property: bot_token
+ # - secretKey: SLACK_APP_TOKEN
+ # remoteRef:
+ # key: prod/slack-bot
+ # property: app_token
+ # - secretKey: SLACK_SIGNING_SECRET
+ # remoteRef:
+ # key: prod/slack-bot
+ # property: signing_secret
+ # - secretKey: SLACK_CLIENT_SECRET
+ # remoteRef:
+ # key: prod/slack-bot
+ # property: slack_client_secret
+ # - secretKey: SLACK_LINK_HMAC_SECRET
+ # remoteRef:
+ # key: prod/slack-bot
+ # property: slack_link_hmac_secret
+ # - secretKey: OAUTH2_CLIENT_SECRET
+ # remoteRef:
+ # key: prod/slack-bot
+ # property: oauth2_client_secret
+ # - secretKey: KEYCLOAK_BOT_CLIENT_SECRET
+ # remoteRef:
+ # key: prod/slack-bot
+ # property: keycloak_bot_client_secret
+ # - secretKey: KEYCLOAK_SLACK_BOT_ADMIN_CLIENT_SECRET
+ # remoteRef:
+ # key: prod/slack-bot
+ # property: keycloak_slack_bot_admin_client_secret

resources:
requests:
@@ -976,6 +1185,215 @@
cpu: 500m
memory: 512Mi

+######### Webex Bot Integration configuration #########
+# Parallel to slack-bot: Webex spaces, identity linking, and OpenFGA ReBAC.
+# Enable with Helm tag: webex-bot=true
+webex-bot:
+ image:
+ repository: "ghcr.io/cnoe-io/caipe-webex-bot"
+ tag: ""
+ pullPolicy: "IfNotPresent"
+
+ config:
+ APP_NAME: "CAIPE"
+ CAIPE_API_URL: "http://ai-platform-engineering-caipe-ui:3000"
+ WEBEX_WORKSPACE_ALIAS: "CAIPE-WEBEX"
+ WEBEX_AGENT_ROUTES_MODE: "db_prefer"
+ WEBEX_THREAD_CONTEXT_ENABLED: "true"
+ WEBEX_THREAD_CONTEXT_MAX_MESSAGES: "10"
+ WEBEX_THREAD_CONTEXT_MAX_CHARS: "4000"
+ WEBEX_AUTO_ASSIGN_UNMAPPED_SPACES: "false"
+ WEBEX_DEFAULT_TEAM_SLUG: ""
+ WEBEX_DEFAULT_AGENT_ID: ""
+ WEBEX_ADMIN_API_ENABLED: "false"
+ WEBEX_ADMIN_API_HOST: "0.0.0.0"
+ WEBEX_ADMIN_API_PORT: "3002"
+ WEBEX_ADMIN_JWT_ISSUER: "http://ai-platform-engineering-keycloak:8080/realms/caipe"
+ WEBEX_ADMIN_JWKS_URL: "http://ai-platform-engineering-keycloak:8080/realms/caipe/protocol/openid-connect/certs"
+ WEBEX_ADMIN_JWT_AUDIENCE: "caipe-webex-bot-admin"
+ WEBEX_ADMIN_ALLOWED_CLIENT_IDS: "caipe-ui"
+ KEYCLOAK_URL: "http://ai-platform-engineering-keycloak:8080"
+ KEYCLOAK_REALM: "caipe"
+ OPENFGA_HTTP: "http://ai-platform-engineering-openfga:8080"
+ OPENFGA_STORE_NAME: "caipe-openfga"
+
+ # Wire OBO secret from Keycloak chart (see keycloak/templates/NOTES.txt).
+ keycloakBot:
+ clientSecretFromSecret:
+ name: "ai-platform-engineering-keycloak-webex-bot"
+ key: "KC_WEBEX_BOT_CLIENT_SECRET"
+
+ existingSecret: "webex-bot-secrets"
+
+ botConfig: {}
+
+ externalSecrets:
+ enabled: false
+ apiVersion: "v1beta1"
+ secretStoreRef:
+ name: "vault"
+ kind: "ClusterSecretStore"
+ data: []
+
+ resources:
+ requests:
+ cpu: 100m
+ memory: 256Mi
+ limits:
+ cpu: 500m
+ memory: 512Mi
+
+######### Keycloak Identity Provider configuration #########
+# Keycloak provides RBAC, identity federation (upstream SSO broker),
+# and token exchange (RFC 8693) for the Slack bot.
+# Enable with tag: keycloak=true
+keycloak:
+ image:
+ repository: "quay.io/keycloak/keycloak"
+ tag: "26.3"
+ pullPolicy: IfNotPresent
+
+ # Admin credentials — auto-generated random password by default.
+ # For prod: set admin.secretRef to an existing Secret, or enable
+ # externalSecrets to pull from Vault / AWS Secrets Manager.
+ admin:
+ username: admin
+ password: "" # Leave empty for auto-generated 32-char password
+ secretRef: "" # Set to an existing K8s Secret name with keys: username, password
+
+ realm:
+ name: caipe
+ sslRequired: "external" # "none" for dev, "external" for prod
+
+ # Keycloak features
+ features:
+ tokenExchange: true
+ adminFineGrainedAuthz: true
+
+ # Token exchange setup — enables bot impersonation via RFC 8693
+ tokenExchange:
+ enabled: true
+ botClientId: "caipe-slack-bot"
+ webexTokenExchange:
+ enabled: true
+ botClientId: "caipe-webex-bot"
+
+ # CAIPE platform OIDC client (the supervisor confidential client).
+ #
+ # R1 upstream fix (May 2026): the umbrella defaults `secretRef` to
+ # `caipe-platform-secret` so the keycloak chart's
+ # `platformClientSecretName` helper and the caipe-ui Deployment's
+ # `KEYCLOAK_ADMIN_CLIENT_SECRET` valueFrom.secretKeyRef both resolve
+ # to the same Secret name. An operator who:
+ # - pre-creates a K8s Secret called `caipe-platform-secret` with
+ # key `OIDC_CLIENT_SECRET`, OR
+ # - enables `externalSecret.enabled=true` (ESO emits a Secret of
+ # this same name as its target),
+ # gets the full BFF → Keycloak Admin REST wiring out of the box.
+ #
+ # Migration for existing ESO installs that used the OLD default name
+ # `<release>-keycloak-platform-client`: see
+ # docs/docs/security/rbac/secrets-bootstrap.md → R1 upstream fix.
+ # assisted-by Claude:claude-opus-4-7
+ platformClient:
+ secretRef: "caipe-platform-secret"
+
+ # Upstream IDP broker (generic OIDC — works with Okta, Azure AD, Duo, etc.)
+ # No vendor-specific credentials stored here.
+ idp:
+ enabled: false
+ alias: "" # e.g. "upstream-sso"
+ displayName: "" # e.g. "Enterprise SSO"
+ issuer: "" # OIDC issuer URL
+ clientId: ""
+ secretRef: "" # K8s Secret with key: IDP_CLIENT_SECRET
+ accessGroup: "" # Optional upstream group reference; mirrored into idp_groups only
+ adminGroup: "" # Optional upstream admin group reference; map to OpenFGA admin via Identity Group Sync
+
+ # External Secrets for admin password
+ externalSecrets:
+ enabled: false
+ apiVersion: "v1beta1"
+ secretStoreRef:
+ name: "vault"
+ kind: "ClusterSecretStore"
+ data: []
+ # - secretKey: password
+ # remoteRef:
+ # key: prod/keycloak
+ # property: admin_password
+
+ service:
+ type: ClusterIP
+ port: 8080
+
+ resources:
+ requests:
+ cpu: 250m
+ memory: 512Mi
+ limits:
+ cpu: "1"
+ memory: 1Gi
+
+######### OpenFGA Relationship PDP configuration #########
+# OpenFGA stores team/resource tuples used by the UI and the AgentGateway
+# ext_authz bridge. Enable for RBAC/ReBAC installs.
+openfga:
+ enabled: false
+ image:
+ repository: openfga/openfga
+ tag: v1.15.1
+ pullPolicy: IfNotPresent
+ init:
+ enabled: true
+ storeName: caipe-openfga
+ seedTuples: []
+ datastore:
+ engine: memory
+ uriSecretRef:
+ name: ""
+ key: OPENFGA_DATASTORE_URI
+ migrate:
+ enabled: true
+
+######### OpenFGA AgentGateway ext_authz bridge #########
+# The bridge receives Envoy ext_authz checks from AgentGateway and performs
+# OpenFGA Check calls. Enable alongside OpenFGA and AgentGateway.
+openfgaAuthzBridge:
+ enabled: false
+
+# Values for the openfga-authz-bridge subchart. The separate camelCase block
+# above is kept as the dependency condition flag.
+openfga-authz-bridge:
+ image:
+ repository: ghcr.io/cnoe-io/openfga-authz-bridge
+ tag: ""
+ pullPolicy: IfNotPresent
+ openfga:
+ httpUrl: "http://{{ .Release.Name }}-openfga:8080"
+ storeName: caipe-openfga
+ relation: can_call
+ object: mcp_gateway:list
+ agentContext:
+ existingSecret:
+ name: ""
+ key: CAIPE_AGENT_CONTEXT_HMAC_SECRET
+ tokenValidation:
+ jwksUrl: "http://{{ .Release.Name }}-keycloak:8080/realms/caipe/protocol/openid-connect/certs"
+ issuer: ""
+ audiences: []
+ algorithms:
+ - RS256
+ audit:
+ enabled: true
+ mongodbUri: ""
+ mongodbDatabase: caipe
+ tenantId: default
+ subjectSalt: caipe-098-audit
+ existingSecret:
+ name: ""
+ key: MONGODB_URI
+
######### RAG Stack configuration #########
# RAG Stack - Complete stack including web, server, agent, Redis, and Milvus
# Below values are only a subset of the values that are available in the rag-stack chart.