Skip to content
Agent Orchestration
Skill

/ambient-ui

Deploy, update manifests, and troubleshoot the ambient-ui component. Use when creating or modifying deployment manifests, adding ambient-ui to a new overlay, building images, or debugging cluster issues.

BOOST
From plugin
platform
13121 skills6 agents11 commands3 MCP
Install
$ npx -y skills add ambient-code/platform --skill ambient-ui --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/ambient-ui

Context preview

The summary Claude sees to decide when to auto-load this skill.

Deploy, update manifests, and troubleshoot the ambient-ui component. Use when creating or modifying deployment manifests, adding ambient-ui to a new overlay, building images, or debugging cluster issues.

SKILL.md

ambient-ui.SKILL.md
name: deploy
description: >
  Deploy, update manifests, and troubleshoot the ambient-ui component.
  Use when creating or modifying deployment manifests, adding ambient-ui
  to a new overlay, building images, or debugging cluster issues.

Ambient UI Deployment

Instructions for deploying the ambient-ui component across environments.

User Input

$ARGUMENTS

Architecture

The ambient-ui is a Next.js BFF (Backend-for-Frontend) that handles OIDC authentication as a confidential client, manages server-side sessions, and proxies API requests to the ambient-api-server with JWT relay.

Route (port 443, TLS edge termination)
  → Service (port 3000)
    → Next.js BFF (port 3000)
      ├── OIDC auth (Authorization Code Flow + PKCE against Red Hat SSO)
      ├── Server-side session (iron-session, httpOnly cookie)
      ├── JWT relay to ambient-api-server (Authorization: Bearer <jwt>)
      └── ambient-api-server (port 8000, HTTPS, validates JWT against same issuer)

No sidecar proxy. The BFF IS the confidential OIDC client. The browser never receives a raw JWT — only an httpOnly session cookie.

Manifest File Map

| File | Purpose | |------|---------| | `components/manifests/base/core/ambient-ui-deployment.yaml` | Base Deployment, ServiceAccount, Service | | `components/manifests/overlays/kind/kustomization.yaml` | Kind overlay (Quay images, no auth) | | `components/manifests/overlays/kind-local/kustomization.yaml` | Kind-local overlay (localhost images) | | `components/ambient-ui/Dockerfile` | Multi-stage Docker build | | `.github/workflows/components-build-deploy.yml` | CI build matrix entry | | `components/manifests/overlays/hcmais/kustomization.yaml` | HCMAIS overlay (ambient-api namespace, Keycloak SSO) |

Production overlay files exist (`ambient-ui-oauth-patch.yaml`, etc.) but are disabled — they used origin-oauth-proxy which can't produce JWTs. See Auth section.

Docker Build

**Build context** is `./components` (not `./components/ambient-ui`), because the Dockerfile references `ambient-sdk/ts-sdk` as a sibling.

Critical details

1. **SDK dist/ is gitignored.** The Dockerfile must build it:

   COPY ambient-sdk/ts-sdk /ambient-sdk/ts-sdk
   RUN cd /ambient-sdk/ts-sdk && npm install --ignore-scripts && npm run build

2. **Standalone output path.** `outputFileTracingRoot: ../..` in next.config.js resolves to `/` in Docker (WORKDIR `/app`), so standalone nests under `app/`:

   cp -r .next/standalone/app/. /app-output/

Locally it nests under `components/ambient-ui/`. Always verify with:

   find .next/standalone -name server.js -not -path '*/node_modules/*'

3. **Webpack, not Turbopack.** The build script is `next build --webpack`. Turbopack cannot resolve `file:` linked dependencies.

4. **OpenShift permissions.** The builder stage must run:

   chmod -R g=u /app-output && chgrp -R 0 /app-output

The runner image (Red Hat Hardened Image) is distroless — no shell at runtime.

Local build & test

podman build -t ambient-ui-test -f components/ambient-ui/Dockerfile components/
podman run --rm ambient-ui-test node -e 'require("fs").statSync("/app/server.js"); console.log("server.js found")'
podman run -d --name ambient-ui-test -e HOSTNAME=0.0.0.0 ambient-ui-test
podman exec ambient-ui-test node -e "require('http').get('http://localhost:3000/', r => { console.log(r.statusCode); r.on('data',()=>{}); r.on('end',()=>process.exit(0)); })"
podman stop ambient-ui-test && podman rm ambient-ui-test

Environment Configuration

| Env Var | kind / local | Production | |---------|-------------|------------| | `API_SERVER_URL` | `http://ambient-api-server:8000` | `https://ambient-api-server:8000` | | `NODE_EXTRA_CA_CERTS` | (unset) | `/etc/ssl/service-ca/service-ca.crt` (from service-ca ConfigMap) | | `SSO_ISSUER_URL` | Keycloak realm URL (auto-generated by `make dev COMPONENT=ambient-ui`) | `https://sso.redhat.com/auth/realms/redhat-external` | | `SSO_CLIENT_ID` | `ambient-frontend` (Kind Keycloak) | OIDC client ID | | `SSO_CLIENT_SECRET` | `dev-secret-do-not-use-in-prod` (Kind Keycloak) | OIDC client secret (from Secret) | | `SESSION_SECRET` | auto-generated from cluster name | Random 32+ byte string (from Secret) | | `NEXT_PUBLIC_PREVIEW_ALLOWED_HOSTS` | (unset, defaults `localhost:*`) | target domains |

Authentication

Native SSO (target architecture)

The BFF handles OIDC directly using Authorization Code Flow with PKCE:

1. User visits ambient-ui → BFF redirects to SSO issuer authorize endpoint 2. User authenticates at Red Hat SSO → redirected back with auth code 3. BFF exchanges code for tokens (access token = JWT, refresh token, ID token) 4. BFF stores tokens in an iron-session encrypted httpOnly cookie 5. On API requests, BFF extracts JWT from session and forwards as `Authorization: Bearer` 6. ambient-api-server validates JWT against `sso.redhat.com` JWKS endpoint

This is already implemented in:

  • `src/lib/oidc.ts` — OIDC discovery, auth URL, code exchange, token refresh
  • `src/lib/session.ts` — iron-session storage, token expiry, auto-refresh
  • `src/lib/auth.ts` — `resolveAccessToken()` extracts JWT from session
  • `src/app/api/auth/sso/login/route.ts` — initiates OIDC flow
  • `src/app/api/auth/sso/callback/route.ts` — handles callback, stores tokens
  • `src/app/api/auth/sso/logout/route.ts` — destroys session

What's needed to enable native SSO

An OIDC confidential client on `sso.redhat.com/auth/realms/redhat-external`:

  • Client protocol: `openid-connect`, access type: `confidential`
  • Valid redirect URI: `https://<ambient-ui-route>/api/auth/sso/callback`
  • Scopes: `openid`, `email`, `profile`

Then set the env vars: `SSO_ISSUER_URL`, `SSO_CLIENT_ID`, `SSO_CLIENT_SECRET`, `SESSION_SECRET`, and `AUTH_MODE=native-sso`.

Why origin-oauth-proxy doesn't work

The OpenShift `origin-oauth-proxy` issues opaque `sha256~` tokens, not JW

Read more
Ships withplatform

Kubernetes-native AI automation platform for intelligent agentic sessions

Get the whole plugin

Other skills on platform.