Langfuse setup

Control Core pairs inline enforcement (Bouncer + Rego) with optional async LLM observability via self-hosted Langfuse. Langfuse is an optional deployment pick for AI engineers (traces, prompt versions, evaluations, token cost). It is not required for PBAC enforcement or compliance audit.

Grafana is also optional. Compliance evidence flows through the Control Plane audit APIs and your SIEM (Splunk, Microsoft Sentinel, Elastic, QRadar, or custom). Enable Grafana and/or Langfuse only when you want those operator or AI-engineering UIs.

Optional observability picks

ComponentRequired for PBAC / audit?Role when enabled
SIEM / audit outbox (default path)Yes for compliance exportImmutable decisions → Splunk, Sentinel, Elastic, QRadar, custom
Grafana (optional)NoInfrastructure metrics, Loki dashboards, shadow discovery views
Langfuse (optional)NoMulti-turn LLM traces, agent graphs, evals

Canadian sovereignty defaults (customer VPC):

  • TELEMETRY_ENABLED=false — no Langfuse phone-home
  • global.zeroForeignEgress=true — observability stays inside your boundary
  • Images and libraries are pulled online from your approved / Canadian-region registries; no foreign SaaS telemetry egress is required for core Control Core

Enable Langfuse (Helm — AWS Canada)

# Provision Secret controlcore-langfuse-secrets first (database-url, nextauth-secret, salt, encryption-key, clickhouse-url, redis-url, postgres-password).

helm upgrade --install controlcore ./controlcore \
  -f values.yaml \
  -f values-ca-central-1.yaml \
  --set langfuse.enabled=true

Sovereignty defaults (already listed above) also pin storage classes such as gp3-encrypted-ca in ca-central-1 when you deploy on AWS Canada.

Troubleshooting: If pods stay Pending, check nodeSelector zone ca-central-1a and PVC storage class. Confirm Secret keys match the chart. See Troubleshooting.

Bootstrap Langfuse project (~5 min)

After Langfuse pods or Compose services are healthy, seed the default Control Core project (API keys, org, and OTLP ingest settings) with the release helper:

# From your release bundle root
bash scripts/bootstrap-langfuse-demo-project.sh

The script reads Langfuse admin credentials from your Secret or .env, creates a Control Core project if missing, and prints the OTLP endpoint and public/secret keys for Bouncer env. Re-run safely after upgrades — it is idempotent.

Troubleshooting: If the script exits non-zero, confirm Langfuse /api/public/health returns 200 and that database migrations completed. For Compose labs, run bash scripts/enable-aio-langfuse.sh first to start the Langfuse profile.

Connect the Bouncer (OTLP)

Set on each Bouncer:

CC_OTEL_ENABLED=true
CC_OTLP_ENDPOINT=langfuse.<namespace>.svc:4317   # or OTel Collector → Langfuse

Restart the Bouncer after changing env vars so the OTLP exporter picks up the endpoint.

Compose all-in-one stack:

bash scripts/enable-aio-langfuse.sh
# or
COMPOSE_PROFILES=langfuse docker compose \
  -f compose.demo.yml -f compose.demo.langfuse.yml up -d

Langfuse UI (local): http://localhost:3002

Troubleshooting: If no spans appear, verify CC_OTEL_ENABLED=true, Collector/Langfuse OTLP port 4317, and that AI traffic traversed Bouncer intercept. Health: curl -fsS http://localhost:3002/api/public/health.

Air-gap telemetry posture

Self-hosted Langfuse must not phone home to foreign SaaS. Set on Langfuse worker/web and Control Plane when tracing is enabled inside a sovereign enclave:

TELEMETRY_ENABLED=false
LANGFUSE_TELEMETRY_ENABLED=false

Helm (Canadian / air-gap overlay):

global:
  zeroForeignEgress: true
langfuse:
  environment:
    TELEMETRY_ENABLED: "false"
    LANGFUSE_TELEMETRY_ENABLED: "false"

Bouncer OTLP (CC_OTLP_ENDPOINT) must target an in-cluster Langfuse or collector Service — never a public Langfuse Cloud URL in air-gap installs.

Filter traces in Langfuse

Use span attributes emitted by Control Core:

AttributeMeaning
controlcore.decisionALLOW, DENY, REDACT, or shadow WOULD_DENY
controlcore.pii_detectedPII / redaction obligation applied
controlcore.rule_matchedRego rule id
controlcore.spiffe_idWorkload SPIFFE ID when present
controlcore.deployment_modeenforce or shadow

Shadow mode debugging

With BOUNCER_ENFORCEMENT_MODE=shadow, live traffic still pass-through while spans may tag controlcore.decision=WOULD_DENY with controlcore.rule_matched so AI developers can inspect policy impact without blocking users.

Troubleshooting: If you see ALLOW only in shadow, confirm a deny/redact obligation would have fired and that OTel is enabled.

Next steps