From 4c992dd60799f2acc8e7e82e75850c1008d83796 Mon Sep 17 00:00:00 2001 From: Ondrej Metelka Date: Tue, 19 May 2026 17:21:22 +0200 Subject: [PATCH 1/5] Add design spec for LLMProvider TLS certificate support Covers adding an optional tlsCertificate ConfigMap reference to LLMProviderSpec for corporate proxy CA injection into sandbox pods. Co-authored-by: Cursor --- ...5-19-llmprovider-tls-certificate-design.md | 202 ++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 docs/superpowers/specs/2026-05-19-llmprovider-tls-certificate-design.md diff --git a/docs/superpowers/specs/2026-05-19-llmprovider-tls-certificate-design.md b/docs/superpowers/specs/2026-05-19-llmprovider-tls-certificate-design.md new file mode 100644 index 00000000..1a1452b2 --- /dev/null +++ b/docs/superpowers/specs/2026-05-19-llmprovider-tls-certificate-design.md @@ -0,0 +1,202 @@ +# LLMProvider TLS Certificate Support + +**Date:** 2026-05-19 +**Status:** Approved +**Scope:** lightspeed-agentic-operator only (no sandbox changes) + +## Problem + +When an OpenShift cluster sits behind a corporate proxy that performs TLS +interception, HTTPS connections from sandbox pods to LLM provider endpoints +(Anthropic, Vertex AI, OpenAI, etc.) fail with certificate verification +errors. The proxy's CA is not in the container's system trust store. + +Cluster admins need a way to supply an additional CA bundle per LLM provider +so the operator can inject it into sandbox pods. + +## Decision + +Add an optional `tlsCertificate` field to `LLMProviderSpec` that references a +ConfigMap containing PEM-encoded CA certificates. The operator mounts the +ConfigMap into the sandbox pod and uses an init container to concatenate the +custom CA with the system trust store, then sets `SSL_CERT_FILE` and +`NODE_EXTRA_CA_CERTS` so all HTTPS clients in the pod trust the additional CA. + +## Design + +### 1. CRD API + +#### New type: `ConfigMapReference` (`reference_types.go`) + +```go +type ConfigMapReference struct { + // name of the ConfigMap. Must be a valid RFC 1123 DNS subdomain. + // +required + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + // +kubebuilder:validation:XValidation:rule="!format.dns1123Subdomain().validate(self).hasValue()",message="must be a valid DNS subdomain: lowercase alphanumeric characters, hyphens, and dots" + Name string `json:"name,omitempty"` +} +``` + +#### Modified: `LLMProviderSpec` (`llmprovider_types.go`) + +Add a new optional field at the top level of the spec (not inside per-provider +configs), because the CA is about the network path to the provider, not the +provider type: + +```go +type LLMProviderSpec struct { + Type LLMProviderType `json:"type,omitempty"` + + // tlsCertificate optionally references a ConfigMap containing a custom + // CA bundle for TLS connections to this provider's endpoint. Used when + // the provider is behind a TLS-intercepting proxy or uses a private CA. + // + // The ConfigMap must exist in the operator namespace (openshift-lightspeed) + // and contain the key "ca-bundle.crt" with PEM-encoded CA certificates. + // The certificates are appended to the system trust store in the sandbox + // pod so that all HTTPS clients (Python SDKs, Node.js Claude Code, curl, + // oc) trust the additional CA. + // + // When omitted, the sandbox pod uses only the default system trust store. + // +optional + TLSCertificate *ConfigMapReference `json:"tlsCertificate,omitzero"` + + Anthropic AnthropicConfig `json:"anthropic,omitzero"` + GoogleCloudVertex GoogleCloudVertexConfig `json:"googleCloudVertex,omitzero"` + OpenAI OpenAIConfig `json:"openAI,omitzero"` + AzureOpenAI AzureOpenAIConfig `json:"azureOpenAI,omitzero"` + AWSBedrock AWSBedrockConfig `json:"awsBedrock,omitzero"` +} +``` + +### 2. Operator Template Patching (`sandbox_templates.go`) + +New function `patchTLSCertificate` called from `EnsureAgentTemplate` after +`patchLLMCredentials`, when `llm.Spec.TLSCertificate != nil`. + +#### Volumes + +| Volume name | Type | Source | +|-------------------|-----------|------------------------------------------------------| +| `llm-ca-bundle` | configMap | ConfigMap named by `tlsCertificate.name`, key `ca-bundle.crt` | +| `llm-ca-combined` | emptyDir | Shared between init container and main container | + +#### Init container + +- **Name:** `merge-ca-bundle` +- **Image:** Same as the first container in the base template (the sandbox image) +- **Command:** + ``` + ["sh", "-c", + "cat /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem /var/run/secrets/llm-ca/ca-bundle.crt > /tmp/ca-bundle/combined-ca-bundle.crt"] + ``` +- **Volume mounts:** + - `llm-ca-bundle` → `/var/run/secrets/llm-ca` (readOnly: true) + - `llm-ca-combined` → `/tmp/ca-bundle` + +The system CA path `/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem` is the +standard location in UBI/RHEL-based images (which the sandbox uses). + +#### Main container modifications + +- **Volume mount:** `llm-ca-combined` → `/tmp/ca-bundle` (readOnly: true) +- **Environment variables:** + - `SSL_CERT_FILE=/tmp/ca-bundle/combined-ca-bundle.crt` — honored by + Python `ssl`, `requests`, `httpx`, `curl`, `oc`, and most C-based TLS + libraries + - `NODE_EXTRA_CA_CERTS=/tmp/ca-bundle/combined-ca-bundle.crt` — honored by + Node.js (Claude Code). Node appends these to its compiled-in CA store. + +#### Template hash + +Add the ConfigMap name (or empty string when absent) to `templateHashInput` +so a CA configuration change produces a new derived template and triggers +garbage collection of the old one. + +```go +type templateHashInput struct { + LLM agenticv1alpha1.LLMProviderSpec `json:"llm"` + Model string `json:"model"` + Skills []agenticv1alpha1.SkillsSource `json:"skills"` + MCPServers []agenticv1alpha1.MCPServerConfig `json:"mcpServers,omitempty"` + RequiredSecrets []agenticv1alpha1.SecretRequirement `json:"requiredSecrets,omitempty"` + Step string `json:"step"` + BaseResourceVersion string `json:"baseRV"` +} +``` + +No change needed — `LLM` already serializes the full `LLMProviderSpec`, so +adding `TLSCertificate` to the spec struct automatically includes it in the +hash input. + +### 3. Example YAML + +Admin creates a ConfigMap with the proxy CA: + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: corporate-proxy-ca + namespace: openshift-lightspeed +data: + ca-bundle.crt: | + -----BEGIN CERTIFICATE----- + MIIDxTCCAq2gAwIBAgI... + -----END CERTIFICATE----- +``` + +LLMProvider references it: + +```yaml +apiVersion: agentic.openshift.io/v1alpha1 +kind: LLMProvider +metadata: + name: anthropic-via-proxy +spec: + type: Anthropic + tlsCertificate: + name: corporate-proxy-ca + anthropic: + credentialsSecret: + name: llm-credentials + url: https://api.anthropic.com +``` + +### 4. Testing + +| Test | What it verifies | +|-----------------------------------------|----------------------------------------------------------------------| +| `TestPatchTLSCertificate_AddsVolumes` | ConfigMap volume + emptyDir volume added to pod spec | +| `TestPatchTLSCertificate_AddsInitContainer` | Init container present with correct command and mounts | +| `TestPatchTLSCertificate_SetsEnvVars` | `SSL_CERT_FILE` and `NODE_EXTRA_CA_CERTS` set on main container | +| `TestPatchTLSCertificate_NoOp` | No TLS certificate → no volumes, no init container, no env vars | +| `TestTemplateHash_ChangesWithCA` | Hash differs when `tlsCertificate` is added/changed/removed | +| `TestEnsureAgentTemplate_WithCA` | Full integration: base template + CA → derived template is correct | + +## Out of Scope + +- **No sandbox-side changes.** CA injection is purely pod-template-level. +- **No cluster-wide CA.** Per-LLMProvider only. A global default can be added + later as a field on a cluster-scoped config CRD. +- **No cert rotation for running pods.** Sandbox pods are ephemeral. New pods + pick up ConfigMap changes automatically. +- **No mTLS.** Server CA trust only, not client certificate authentication. +- **No ConfigMap existence validation.** The operator does not verify the + ConfigMap exists at reconcile time. A missing ConfigMap causes a pod + scheduling failure, which is the standard Kubernetes behavior and is + surfaced via pod events. + +## Files Changed + +| File | Change | +|-----------------------------------------------|--------------------------------------------------------| +| `api/v1alpha1/reference_types.go` | Add `ConfigMapReference` type | +| `api/v1alpha1/llmprovider_types.go` | Add `TLSCertificate *ConfigMapReference` to spec | +| `controller/proposal/sandbox_templates.go` | Add `patchTLSCertificate`, call from `EnsureAgentTemplate` | +| `controller/proposal/sandbox_templates_test.go` | Add CA patching tests | +| `config/crd/bases/` (generated) | Regenerated via `make manifests` | +| `api/v1alpha1/zz_generated.deepcopy.go` (generated) | Regenerated via `make generate` | +| `examples/setup/00-llm-providers.yaml` | Add example with `tlsCertificate` | From f8e7e8eb1aef5809728e7f00aba0f78531dd8558 Mon Sep 17 00:00:00 2001 From: Ondrej Metelka Date: Tue, 19 May 2026 17:33:58 +0200 Subject: [PATCH 2/5] Update project specs for LLMProvider TLS certificate support - crd-api.md: Add rule 22 for spec.tlsCertificate ConfigMapReference, add ConfigMapReference to shared types, update LLMProvider config surface - sandbox-execution.md: Add rule 17 for TLS CA bundle injection behavior (ConfigMap mount, init container concatenation, SSL_CERT_FILE, NODE_EXTRA_CA_CERTS), update planned changes - reconciler.md: Add patchTLSCertificate and addInitContainer to module map, update EnsureAgentTemplate description Co-authored-by: Cursor --- .ai/spec/how/reconciler.md | 4 +-- .ai/spec/what/crd-api.md | 44 ++++++++++++++++-------------- .ai/spec/what/sandbox-execution.md | 31 +++++++++++---------- 3 files changed, 41 insertions(+), 38 deletions(-) diff --git a/.ai/spec/how/reconciler.md b/.ai/spec/how/reconciler.md index aabd66d3..93527616 100644 --- a/.ai/spec/how/reconciler.md +++ b/.ai/spec/how/reconciler.md @@ -28,7 +28,7 @@ Audience: AI agents. Behavioral rules and phase semantics live in **what/** spec | `agent.go` | `AgentCaller`, `StubAgentCaller`; `AnalysisOutput`, `ExecutionOutput`, `VerificationOutput`, `EscalationOutput` | Interface methods on `StubAgentCaller` | | `sandbox.go` | `SandboxProvider`, `SandboxManager` | `NewSandboxManager`, `Claim`, `WaitReady`, `Release`, `buildClaim` | | `sandbox_agent.go` | `SandboxAgentCaller`; private JSON DTOs for unmarshaling agent responses local to this file | `NewSandboxAgentCaller`, `Analyze`, `Execute`, `Verify`, `Escalate`, `ReleaseSandboxes`, `callWithSandbox`, `patchSandboxInfo`, `buildAgentContext`, `collectFailedResults`, `stepString` | -| `sandbox_templates.go` | `templateHashInput`; label constants (`LabelManaged`, `LabelProposal`, etc.); MCP env DTOs | `EnsureAgentTemplate`, `SandboxTemplateServiceAccount`, `computeTemplateHash`, `agentTemplateName`, `gcOldTemplates`, `patchLLMCredentials`, `credentialsSecretName`, `providerURL`, `patchRequiredSecrets`, `patchMCPServers`, `patchSkillsImage`, `patchSkillsPaths`, `patchAgentMode`, unstructured helpers (`firstContainer`, `setEnvVar`, `addEnvFromSecret`, …) | +| `sandbox_templates.go` | `templateHashInput`; label constants (`LabelManaged`, `LabelProposal`, etc.); MCP env DTOs | `EnsureAgentTemplate`, `SandboxTemplateServiceAccount`, `computeTemplateHash`, `agentTemplateName`, `gcOldTemplates`, `patchLLMCredentials`, `patchTLSCertificate`, `credentialsSecretName`, `providerURL`, `patchRequiredSecrets`, `patchMCPServers`, `patchSkillsImage`, `patchSkillsPaths`, `patchAgentMode`, unstructured helpers (`firstContainer`, `setEnvVar`, `addEnvFromSecret`, `addInitContainer`, …) | | `client.go` | `AgentHTTPClientInterface`, `AgentHTTPClient`; `agentRunRequest`, `agentContext`, `agentExecutionResult`, `agentPreviousAttempt`, `agentRunResponse` | `NewAgentHTTPClient`, `(*AgentHTTPClient).Run`, `executionOutputToAgentResult` | | `schemas.go` | Package vars: default/minimal analysis schemas, execution/verification/escalation schemas; `defaultOutputSchemas`, `builtInPropertyJSON` | `init` (precompute property JSON), `injectBuiltInProperty`, `outputSchemaForStep` | | `rbac.go` | — | `ensureExecutionRBAC`, `cleanupExecutionRBAC`, `annotatedRBACNamespaces`, `deleteIfExists`, `rbacTargetNamespaces`, `truncateK8sName`, `executionRoleName`, `clusterRoleName`, `rbacLabels`, `rbacRulesToPolicyRules`, `normalizeCoreAPIGroup` | @@ -145,7 +145,7 @@ Audience: AI agents. Behavioral rules and phase semantics live in **what/** spec - **`AgentCaller`:** Boundary between reconciler and runtime (stub vs sandbox+HTTP). Methods mirror workflow steps plus `ReleaseSandboxes`. - **`SandboxProvider`:** Swappable claim/wait/release (tests can fake). - **`resolveProposal`:** Produces `resolvedWorkflow` with cached `Agent` + `LLMProvider` per name; applies per-stage agent overrides from `ProposalApproval` via `getStageOverrideAgent`; `Execution`/`Verification` steps nil when corresponding spec sections are zero. -- **`EnsureAgentTemplate`:** Deterministic derived `SandboxTemplate` name from hash of LLM spec, model, skills, MCP servers, required secrets, step, and **base template resourceVersion**. Patches pod template env/volumes for credentials, Vertex/Bedrock/Azure extras, skills image/paths, MCP JSON env, `LIGHTSPEED_MODE`. GC older templates labeled for same agent+step. +- **`EnsureAgentTemplate`:** Deterministic derived `SandboxTemplate` name from hash of LLM spec, model, skills, MCP servers, required secrets, step, and **base template resourceVersion**. Patches pod template env/volumes for credentials, Vertex/Bedrock/Azure extras, optional TLS CA bundle (init container + `SSL_CERT_FILE` + `NODE_EXTRA_CA_CERTS`), skills image/paths, MCP JSON env, `LIGHTSPEED_MODE`. GC older templates labeled for same agent+step. --- diff --git a/.ai/spec/what/crd-api.md b/.ai/spec/what/crd-api.md index 85d9fe32..be093dce 100644 --- a/.ai/spec/what/crd-api.md +++ b/.ai/spec/what/crd-api.md @@ -25,26 +25,27 @@ Kubernetes API surface for the agentic operator. **Lifecycle and gates** are in 19. **LLMProvider — discriminator**: `spec.type` MUST match exactly one embedded config: `anthropic`, `googleCloudVertex`, `openAI`, `azureOpenAI`, or `awsBedrock`; CEL enforces mutual exclusion. 20. **LLMProvider — secrets**: Each provider’s `credentialsSecret` references a `Secret` **by name** in the operator namespace (documented on fields as the deployment namespace for the operator, e.g. OpenShift Lightspeed namespace); required secret **keys** are defined per provider type on the API field comments (e.g. API key env file key names). 21. **LLMProvider — endpoints**: Optional URL overrides per provider; validation enforces HTTP/HTTPS URL shape. Azure requires `endpoint`; optional separate URL override field exists where defined. -22. **ApprovalPolicy — singleton name**: CRD validation requires `metadata.name` equals `cluster`. -23. **ApprovalPolicy — `spec.stages`**: Optional list keyed by `name` (`SandboxStep`). Each entry sets `approval` to `Automatic` or `Manual`. Stages not listed default to **Manual** per API comments. -24. **ApprovalPolicy — `spec.maxAttempts`**: Upper bound for execution attempts (initial + retries) when verification fails; default behavior when unset is defined in controller (see `approval.md`). -25. **ApprovalPolicy — `spec.maxConcurrentProposals`**: Caps concurrent reconciles when positive; operator falls back to a default constant when unset. -26. **ProposalApproval — pairing**: For each `Proposal`, the controller MUST create (if missing) a same-named `ProposalApproval` in the same namespace with controller owner reference to the `Proposal`. -27. **ProposalApproval — `spec.stages`**: Append-only map list keyed by `type` (`ApprovalStageType`). Each stage carries a discriminated union: exactly one of `analysis`, `execution`, `verification`, `escalation` MUST be present matching `type`. Optional `decision` may be `Approved` (default when omitted) or `Denied`; `Denied` is terminal per API rules. -28. **ProposalApproval — immutability CEL**: Stages cannot be removed; decisions cannot change once set; execution `maxAttempts` cannot decrease once set. -29. **Execution approval fields**: `spec.stages[].execution.option` selects 0-based analysis option index; `maxAttempts` caps attempts but MUST NOT exceed policy `maxAttempts`; `agent` overrides the `Proposal` step’s agent when set. -30. **AnalysisResult**: `spec.proposalName` immutable; `status.options` holds `RemediationOption` entries; `status.sandbox` and `status.failureReason` optional; conditions use shared result condition types. -31. **ExecutionResult**: Adds `spec.retryIndex` (bound to allowed retry range per field validation); `status.actionsTaken`, `status.verification` (inline), optional `failureReason`, `sandbox`. -32. **VerificationResult**: `spec.retryIndex` parallels execution for the same attempt cluster; `status.checks`, `status.summary`, optional `failureReason`, `sandbox`. -33. **EscalationResult**: `status.summary`, `status.content`, optional `failureReason`, `sandbox`; no `retryIndex`. -34. **RemediationOption**: Cohesion rules require `diagnosis` and `proposal` to be paired when present; `components` holds schemaless JSON for adapter data shaped by `spec.analysisOutput.schema`. -35. **RBACResult / RBACRule**: Analysis MAY request namespace-scoped and cluster-scoped rules with verb/apigroup/resource metadata and mandatory `justification`; `namespace` on rules MUST align with proposal targeting rules (validated at runtime by policy engine per field comments). -36. **ToolsSpec**: MAY include `skills` (unique images), `mcpServers` (unique names), `requiredSecrets` (unique names). `SkillsSource.image` MUST be a valid pullspec; optional `paths` restrict mounted subtrees. -37. **SecretRequirement**: Names a namespace-local `Secret`; `mountAs` discriminates `EnvVar` vs `FilePath` with required nested config per type. -38. **MCPHeaderValueSource**: Discriminated by `type`; `Secret` requires nested `secret` name reference. -39. **Result CR ownership**: Result CRs MUST declare controller `ownerReferences` to their `Proposal` for GC; naming follows operator conventions (see `sandbox-execution.md` for when they are created). -40. **Label conventions**: Operator uses labels for proposal name, step, component, and managed template markers (exact keys are implementation-specific; behavior: selectors for GC/list, not duplicated here). -41. **CEL immutability** (Proposal): Enforced transitions include: `request`, `targetNamespaces`, `analysisOutput`, `tools`, `analysis`, `execution`, `verification` immutability after initial set as encoded in API markers. +22. **LLMProvider — `spec.tlsCertificate`**: Optional `ConfigMapReference` naming a ConfigMap in the operator namespace containing a PEM-encoded CA bundle under the key `ca-bundle.crt`. When set, the operator injects the CA into derived sandbox templates so all HTTPS clients trust the additional CA (see `sandbox-execution.md`). When omitted, sandbox pods use only the default system trust store. +23. **ApprovalPolicy — singleton name**: CRD validation requires `metadata.name` equals `cluster`. +24. **ApprovalPolicy — `spec.stages`**: Optional list keyed by `name` (`SandboxStep`). Each entry sets `approval` to `Automatic` or `Manual`. Stages not listed default to **Manual** per API comments. +25. **ApprovalPolicy — `spec.maxAttempts`**: Upper bound for execution attempts (initial + retries) when verification fails; default behavior when unset is defined in controller (see `approval.md`). +26. **ApprovalPolicy — `spec.maxConcurrentProposals`**: Caps concurrent reconciles when positive; operator falls back to a default constant when unset. +27. **ProposalApproval — pairing**: For each `Proposal`, the controller MUST create (if missing) a same-named `ProposalApproval` in the same namespace with controller owner reference to the `Proposal`. +28. **ProposalApproval — `spec.stages`**: Append-only map list keyed by `type` (`ApprovalStageType`). Each stage carries a discriminated union: exactly one of `analysis`, `execution`, `verification`, `escalation` MUST be present matching `type`. Optional `decision` may be `Approved` (default when omitted) or `Denied`; `Denied` is terminal per API rules. +29. **ProposalApproval — immutability CEL**: Stages cannot be removed; decisions cannot change once set; execution `maxAttempts` cannot decrease once set. +30. **Execution approval fields**: `spec.stages[].execution.option` selects 0-based analysis option index; `maxAttempts` caps attempts but MUST NOT exceed policy `maxAttempts`; `agent` overrides the `Proposal` step’s agent when set. +31. **AnalysisResult**: `spec.proposalName` immutable; `status.options` holds `RemediationOption` entries; `status.sandbox` and `status.failureReason` optional; conditions use shared result condition types. +32. **ExecutionResult**: Adds `spec.retryIndex` (bound to allowed retry range per field validation); `status.actionsTaken`, `status.verification` (inline), optional `failureReason`, `sandbox`. +33. **VerificationResult**: `spec.retryIndex` parallels execution for the same attempt cluster; `status.checks`, `status.summary`, optional `failureReason`, `sandbox`. +34. **EscalationResult**: `status.summary`, `status.content`, optional `failureReason`, `sandbox`; no `retryIndex`. +35. **RemediationOption**: Cohesion rules require `diagnosis` and `proposal` to be paired when present; `components` holds schemaless JSON for adapter data shaped by `spec.analysisOutput.schema`. +36. **RBACResult / RBACRule**: Analysis MAY request namespace-scoped and cluster-scoped rules with verb/apigroup/resource metadata and mandatory `justification`; `namespace` on rules MUST align with proposal targeting rules (validated at runtime by policy engine per field comments). +37. **ToolsSpec**: MAY include `skills` (unique images), `mcpServers` (unique names), `requiredSecrets` (unique names). `SkillsSource.image` MUST be a valid pullspec; optional `paths` restrict mounted subtrees. +38. **SecretRequirement**: Names a namespace-local `Secret`; `mountAs` discriminates `EnvVar` vs `FilePath` with required nested config per type. +39. **MCPHeaderValueSource**: Discriminated by `type`; `Secret` requires nested `secret` name reference. +40. **Result CR ownership**: Result CRs MUST declare controller `ownerReferences` to their `Proposal` for GC; naming follows operator conventions (see `sandbox-execution.md` for when they are created). +41. **Label conventions**: Operator uses labels for proposal name, step, component, and managed template markers (exact keys are implementation-specific; behavior: selectors for GC/list, not duplicated here). +42. **CEL immutability** (Proposal): Enforced transitions include: `request`, `targetNamespaces`, `analysisOutput`, `tools`, `analysis`, `execution`, `verification` immutability after initial set as encoded in API markers. ## Configuration Surface (by path) @@ -57,7 +58,7 @@ Kubernetes API surface for the agentic operator. **Lifecycle and gates** are in - `metadata.name`, `spec.llmProvider.name`, `spec.model`, `spec.timeouts.*`, `spec.maxTurns`, `status.conditions` ### LLMProvider -- `metadata.name`, `spec.type`, `spec.anthropic.*`, `spec.googleCloudVertex.*`, `spec.openAI.*`, `spec.azureOpenAI.*`, `spec.awsBedrock.*` +- `metadata.name`, `spec.type`, `spec.tlsCertificate.name`, `spec.anthropic.*`, `spec.googleCloudVertex.*`, `spec.openAI.*`, `spec.azureOpenAI.*`, `spec.awsBedrock.*` ### ApprovalPolicy - `metadata.name` (must be `cluster`), `spec.stages[]`, `spec.maxAttempts`, `spec.maxConcurrentProposals` @@ -73,6 +74,7 @@ Kubernetes API surface for the agentic operator. **Lifecycle and gates** are in - `SkillsSource`: `image`, `paths[]` - `SecretRequirement`: `name`, `description`, `mountAs.*` - `StepResultRef`: `name`, `outcome` +- `ConfigMapReference`: `name` - `SandboxInfo`: `claimName`, `namespace` ## Constraints diff --git a/.ai/spec/what/sandbox-execution.md b/.ai/spec/what/sandbox-execution.md index 7ce586b5..8afb1df7 100644 --- a/.ai/spec/what/sandbox-execution.md +++ b/.ai/spec/what/sandbox-execution.md @@ -20,19 +20,20 @@ Behavioral specification for how workflow steps run inside ephemeral **sandboxes 14. **Context envelope**: The `context` object MUST include `targetNamespaces` from `spec.targetNamespaces`, synthesized `previousAttempts` from failed prior `status.steps.*.results` entries, `approvedOption` when executing/verifying, and `executionResult` when verifying. Note: the sandbox context prefix formatter (see sandbox `run-api.md`) only expands `targetNamespaces`, `attempt`, `previousAttempts`, and `approvedOption` into the model prompt; `executionResult` is carried in `context` for tracing but verification execution details are primarily conveyed to the model via the `query` body (rendered from the verification template). 15. **Secrets — proposal** `spec.tools.requiredSecrets` / per-step tools: Secret objects MUST live in the **same namespace as the `Proposal`**. Mounting into sandbox MUST honor `SecretMountSpec`: environment variable injection OR file mount at configured absolute path. 16. **Secrets — LLM credentials**: LLM provider credentials MUST be loaded from secret names declared on the `LLMProvider` and wired into the derived template via env/volumes per provider type (including optional file mounts for provider types that require file-based credentials). -17. **Secrets — MCP headers**: When an MCP header sources a Secret, the template MUST mount that secret on a dedicated read-only path suitable for header injection configuration. -18. **Skills volumes**: Skills MUST be conveyed as OCI image volume(s) on the sandbox pod template; when `SkillsSource.paths` is set, the controller MUST mount each path as a `subPath` under the configured skills mount root using stable mount naming derived from the path’s final segment. When multiple `skills` entries exist in `ToolsSpec`, template derivation MUST apply image/path patching based on the **first** non-empty skills source (current behavior). -19. **MCP servers**: MCP configuration MUST be serialized to an environment variable payload listing servers, URLs, timeouts, and header sources so the agent runtime can open MCP connections without CR-specific code in the agent. -20. **Sandbox observability patch**: Immediately after creating a claim, the controller MUST patch `Proposal.status.steps..sandbox` with claim name and operator namespace so consoles/CLIs can tail logs before the sandbox is ready. -21. **Execution RBAC materialization**: When the approved remediation option includes RBAC requests, before execution the controller MUST create namespace-scoped `Role`+`RoleBinding` pairs in each target namespace ClusterRole+ClusterRoleBinding for cluster-scoped rules, binding subjects to the **sandbox service account** used by the template (cluster-wide default name configured in operator). Idempotent create MUST tolerate existing objects. -22. **RBAC subjects namespace**: RoleBindings MUST reference the service account in the **operator namespace** (where sandbox pods run), even when roles live in target namespaces. -23. **RBAC tracking annotation**: The controller SHOULD persist the list of namespaces receiving namespace-scoped RBAC on the `Proposal` via a dedicated annotation so cleanup can run after retries or status resets. -24. **RBAC cleanup**: When the proposal reaches configured terminal outcomes, fails fatally, completes escalation successfully, or is deleted, the controller MUST delete execution RBAC objects it created, using the annotation or equivalent persisted scope information. -25. **Finalizers**: Non-deleted proposals MUST gain a cleanup finalizer before leaving non-terminal phases so deletion can run RBAC and sandbox release hooks safely. -26. **Result CR writes**: After each successful or failed agent invocation (per step), the controller MUST create/update an `AnalysisResult`, `ExecutionResult`, `VerificationResult`, or `EscalationResult` with immutable spec, owner reference to the `Proposal`, started/completed conditions, embedded outcome payload, sandbox reference, and optional `failureReason` for system errors. -27. **Retry index**: `ExecutionResult` and `VerificationResult` MUST record the current execution retry index in spec for correlation with `status.steps.execution.retryCount`. -28. **Sandbox release**: On proposal deletion and on terminal phases (`Completed`, `Denied`, `Escalated`), the controller MUST delete known sandbox claims recorded under `status.steps.*.sandbox` (best-effort aggregation; first error MAY be returned for visibility). -29. **Concurrency cap**: Maximum concurrent proposal reconciles SHOULD respect `ApprovalPolicy.spec.maxConcurrentProposals` when present (see `crd-api.md`). +17. **TLS — additional CA bundle**: When `LLMProvider.spec.tlsCertificate` is set, the controller MUST inject the referenced ConfigMap's `ca-bundle.crt` key into the derived sandbox template. The injection MUST: (a) mount the ConfigMap as a read-only volume, (b) add an init container that concatenates the system CA bundle (`/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem`) with the custom CA into a shared `emptyDir` volume, (c) set `SSL_CERT_FILE` and `NODE_EXTRA_CA_CERTS` on the main container pointing to the combined bundle. This ensures all HTTPS clients in the pod (Python SDKs, Node.js Claude Code, curl, oc) trust the additional CA. When `tlsCertificate` is absent, no CA injection occurs and the pod uses only the default system trust store. +18. **Secrets — MCP headers**: When an MCP header sources a Secret, the template MUST mount that secret on a dedicated read-only path suitable for header injection configuration. +19. **Skills volumes**: Skills MUST be conveyed as OCI image volume(s) on the sandbox pod template; when `SkillsSource.paths` is set, the controller MUST mount each path as a `subPath` under the configured skills mount root using stable mount naming derived from the path’s final segment. When multiple `skills` entries exist in `ToolsSpec`, template derivation MUST apply image/path patching based on the **first** non-empty skills source (current behavior). +20. **MCP servers**: MCP configuration MUST be serialized to an environment variable payload listing servers, URLs, timeouts, and header sources so the agent runtime can open MCP connections without CR-specific code in the agent. +21. **Sandbox observability patch**: Immediately after creating a claim, the controller MUST patch `Proposal.status.steps..sandbox` with claim name and operator namespace so consoles/CLIs can tail logs before the sandbox is ready. +22. **Execution RBAC materialization**: When the approved remediation option includes RBAC requests, before execution the controller MUST create namespace-scoped `Role`+`RoleBinding` pairs in each target namespace ClusterRole+ClusterRoleBinding for cluster-scoped rules, binding subjects to the **sandbox service account** used by the template (cluster-wide default name configured in operator). Idempotent create MUST tolerate existing objects. +23. **RBAC subjects namespace**: RoleBindings MUST reference the service account in the **operator namespace** (where sandbox pods run), even when roles live in target namespaces. +24. **RBAC tracking annotation**: The controller SHOULD persist the list of namespaces receiving namespace-scoped RBAC on the `Proposal` via a dedicated annotation so cleanup can run after retries or status resets. +25. **RBAC cleanup**: When the proposal reaches configured terminal outcomes, fails fatally, completes escalation successfully, or is deleted, the controller MUST delete execution RBAC objects it created, using the annotation or equivalent persisted scope information. +26. **Finalizers**: Non-deleted proposals MUST gain a cleanup finalizer before leaving non-terminal phases so deletion can run RBAC and sandbox release hooks safely. +27. **Result CR writes**: After each successful or failed agent invocation (per step), the controller MUST create/update an `AnalysisResult`, `ExecutionResult`, `VerificationResult`, or `EscalationResult` with immutable spec, owner reference to the `Proposal`, started/completed conditions, embedded outcome payload, sandbox reference, and optional `failureReason` for system errors. +28. **Retry index**: `ExecutionResult` and `VerificationResult` MUST record the current execution retry index in spec for correlation with `status.steps.execution.retryCount`. +29. **Sandbox release**: On proposal deletion and on terminal phases (`Completed`, `Denied`, `Escalated`), the controller MUST delete known sandbox claims recorded under `status.steps.*.sandbox` (best-effort aggregation; first error MAY be returned for visibility). +30. **Concurrency cap**: Maximum concurrent proposal reconciles SHOULD respect `ApprovalPolicy.spec.maxConcurrentProposals` when present (see `crd-api.md`). ## Configuration Surface @@ -42,7 +43,7 @@ Behavioral specification for how workflow steps run inside ephemeral **sandboxes - `spec.tools`, per-step `spec.*.tools` (`SkillsSource`, `MCPServerConfig`, `SecretRequirement`) - `spec.targetNamespaces` and RBAC materialization targets - `spec.analysisOutput` (analysis schema behavior) -- `Agent.spec.model`, `LLMProvider.spec.*` (credentials secret names, endpoints, regional fields) +- `Agent.spec.model`, `LLMProvider.spec.*` (credentials secret names, endpoints, regional fields, optional `tlsCertificate` ConfigMap reference) - `Proposal` annotation `agentic.openshift.io/rbac-namespaces` (RBAC scope for cleanup) - `Proposal` finalizer string `agentic.openshift.io/execution-rbac-cleanup` @@ -55,6 +56,6 @@ Behavioral specification for how workflow steps run inside ephemeral **sandboxes ## Planned Changes - [PLANNED: OLS-2957] **Sandbox template management** UX and CRD ergonomics (base/derived lifecycle, versioning) may change operator/template coupling described in rules 2–4. -- [PLANNED: OLS-3038] **TLS verification and network policy** for agent traffic may replace permissive internal TLS client behavior. +- [PLANNED: OLS-3038] **Network policy** for agent traffic may replace permissive internal TLS client behavior. (TLS CA bundle injection via `LLMProvider.spec.tlsCertificate` is implemented in rule 17; remaining: mTLS, network policies.) - [PLANNED: OLS-3044] **Provider parity**: environment variable contract for non-Claude providers in templates MUST track sandbox image capabilities. - [PLANNED: OLS-2894] Support **multiple concurrent skills images** in template derivation beyond the first `skills` entry if product requires composite skill bundles. From 4232bb9ab378c62d5ff8a6c0637c16c54dbfc515 Mon Sep 17 00:00:00 2001 From: Ondrej Metelka Date: Tue, 26 May 2026 14:02:03 +0200 Subject: [PATCH 3/5] Add prodsec-recommended CodeRabbit security rules Adopts the security configuration from openshift/coderabbit#17 which adds Red Hat Product Security recommended review rules, path-specific security instructions, security scanner tooling, and knowledge base indexing. Adds: - Global review instructions (secrets, crypto, injection, container privileges, sensitive logging, AI attribution) - 18 path-specific security review blocks (injection, web, crypto, containers, K8s/OpenShift, MCP, agents, LLM, supply chain, CI/CD, auth, API gateway, Go, C/C++, database, messaging, model registry) - Security scanners: gitleaks, semgrep, checkov, hadolint, trivy, osvScanner, actionlint, ast-grep - Knowledge base auto-indexing of AGENTS.md, CLAUDE.md, CONTRIBUTING.md - Additional path_filters for node_modules, dist, minified JS, yarn.lock Co-authored-by: Cursor --- .coderabbit.yaml | 327 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 325 insertions(+), 2 deletions(-) diff --git a/.coderabbit.yaml b/.coderabbit.yaml index 99a69fad..98ab7bd0 100644 --- a/.coderabbit.yaml +++ b/.coderabbit.yaml @@ -1,4 +1,4 @@ -# CodeRabbit configuration +# CodeRabbit configuration — lightspeed-agentic-operator # Docs: https://docs.coderabbit.ai/guides/configure-coderabbit reviews: # Profile: "chill" generates fewer comments, focuses on significant issues @@ -22,6 +22,12 @@ reviews: - '!go.sum' - '!api/go.sum' - '!vendor/**' + # Prodsec recommended exclusions + # https://github.com/RedHatProductSecurity/prodsec-skills/blob/main/.coderabbit.yaml + - '!node_modules/**' + - '!dist/**' + - '!*.min.js' + - '!yarn.lock' # Review behavior collapse_walkthrough: true @@ -33,5 +39,322 @@ reviews: # Sequence diagrams for complex logic (chill profile limits these to significant changes) sequence_diagrams: true + # Prodsec recommended review instructions + # https://github.com/RedHatProductSecurity/prodsec-skills/blob/main/.coderabbit.yaml + instructions: + - name: "no-hardcoded-secrets" + instructions: | + Flag hardcoded secrets: API keys, tokens, passwords, private + keys, credentials. Also flag base64 strings >32 chars in config, + URLs with embedded credentials, variables named api_key/secret/ + token/password assigned string literals. + mode: "error" + + - name: "no-weak-crypto" + instructions: | + Flag MD5, SHA1, DES, RC4, 3DES, Blowfish, ECB mode usage. + Flag custom crypto implementations. Flag non-constant-time + comparison of secrets or tokens. + mode: "error" + + - name: "no-injection-vectors" + instructions: | + Flag SQL string concatenation, shell=True with user input, + eval/exec on untrusted data, pickle.loads on untrusted input, + yaml.load without SafeLoader, os.system with variables, + dangerouslySetInnerHTML with user data. + mode: "error" + + - name: "container-privileges" + instructions: | + Flag privileged: true, hostPID, hostNetwork, hostIPC, + SYS_ADMIN capability, running as root without justification, + allowPrivilegeEscalation: true in container/K8s manifests. + mode: "error" + + - name: "no-sensitive-data-in-logs" + instructions: | + Flag logging that may expose passwords, tokens, API keys, + PII (email, SSN, credit card), session IDs, internal + hostnames, or customer data. + mode: "error" + + - name: "ai-attribution" + instructions: | + If AI tools were used (mentioned in PR or commits), verify + Red Hat attribution: Assisted-by or Generated-by trailers. + Flag use of Co-Authored-By for AI tools. + mode: "warning" + + # Prodsec recommended path-specific instructions + # https://github.com/RedHatProductSecurity/prodsec-skills/blob/main/.coderabbit.yaml + path_instructions: + + # ── Injection & input validation ───────────────────────────── + - path: "**/*.{py,js,ts,go,rs,java,rb,php,kt,swift,cs}" + instructions: | + Injection prevention (prodsec-skills): + - SQL: parameterized queries only; no string concatenation + - Command: no shell=True, os.system, or backtick exec with user input + - LDAP/XPath: escape special characters in filters + - Path traversal: canonicalize paths, reject ../ + - Deserialization: no pickle/yaml.load()/eval on untrusted data + - Prototype pollution: no recursive merge of untrusted objects + - Validate at trust boundaries with allow-lists, not deny-lists + - Normalize Unicode and anchor regexes (^$); watch for ReDoS + + # ── Web & frontend security ────────────────────────────────── + - path: "**/*.{html,jsx,tsx,vue,svelte}" + instructions: | + Web security (prodsec-skills): + - No dangerouslySetInnerHTML or v-html with user data + - CSP: no unsafe-inline, no unsafe-eval + - CSRF tokens on state-changing requests + - Cookies: Secure, HttpOnly, SameSite=Strict + - No document.write, eval, new Function with user input + - GraphQL: depth/complexity limits, disable introspection in prod + - File uploads: validate by content magic, cap size, server-generate names + - XML: disable external entities (XXE), reject DTDs from untrusted sources + + # ── Cryptography ───────────────────────────────────────────── + - path: "**/*{crypt,cipher,sign,hash,tls,ssl,cert,key,token}*" + instructions: | + Cryptographic security (prodsec-skills): + - Banned: MD5, SHA1, DES, RC4, 3DES, Blowfish, ECB mode + - Symmetric: AES-256-GCM or ChaCha20-Poly1305 + - Passwords: Argon2id (not bcrypt/scrypt for new code) + - Signing: Ed25519 or ECDSA P-256+ + - Key exchange: X25519 or ECDH P-256+ + - Constant-time comparison for all secret/token data + - Zeroize key material after use (no garbage-collector reliance) + - No custom crypto; use vetted libraries only + - Post-quantum: flag if protecting long-lived secrets + + # ── Container & image hardening ────────────────────────────── + - path: "**/{Dockerfile,Containerfile}*" + instructions: | + Container security (prodsec-skills): + - Base image: UBI minimal or distroless from catalog.redhat.com + - Red Hat images: use floating tags (Red Hat manages updates); + non-RH images: pin by digest + - Multi-stage builds; no build tools in final image + - USER non-root; never run as root + - COPY specific files, not entire context + - No secrets in ENV, ARG, or COPY + - Read-only rootfs where possible + - No package manager cache in final layer + - HEALTHCHECK defined + + # ── Kubernetes & OpenShift ─────────────────────────────────── + - path: "**/*.{yaml,yml}" + instructions: | + If this is a Kubernetes/OpenShift manifest or Helm template: + - securityContext: runAsNonRoot, readOnlyRootFilesystem, + allowPrivilegeEscalation: false + - Drop ALL capabilities, add only what is required + - Resource limits (cpu, memory) on every container + - No hostPID, hostNetwork, hostIPC, privileged: true + - NetworkPolicy defined for the namespace + - OpenShift: SCC must be restricted or custom-scoped + - Liveness + readiness probes defined + - automountServiceAccountToken: false unless needed + - RBAC: least privilege; no cluster-admin for workloads + - Helm: no .Values interpolation in shell commands + + # ── MCP server security ────────────────────────────────────── + - path: "**/{mcp,tool_server,toolserver}/**/*" + instructions: | + MCP server review (prodsec-skills): + - OAuth 2.1 resource server: validate tokens per RFC 9068 + - Enforce scope-based access per tool; no default-allow + - RBAC: per-tool permissions mapped to token scopes/roles + - Sanitize all tool inputs against declared schemas + - Reject path traversal in file-accessing tools + - No credential forwarding to downstream services + - Tool injection: validate registry integrity, reject dynamic + tool loading from untrusted sources + - Container isolation: unprivileged, read-only rootfs + - Audit log all tool invocations with caller identity + - Rate limiting per client/scope + - Reject API keys; require IdP-issued tokens + + # ── MCP client ─────────────────────────────────────────────── + - path: "**/{mcp_client,mcp-client}/**/*" + instructions: | + MCP client review (prodsec-skills): + - OAuth client metadata: register with minimal scopes + - Dynamic registration: validate server response, store + client_id/secret securely + - Protected resource metadata: discover before token request + - Consent: prompt user before granting tool access + - Discovery: validate .well-known endpoints over HTTPS only + + # ── Inference engine & model serving ───────────────────────── + - path: "**/{inference,model,serving,predict}/**/*" + instructions: | + Inference engine review (prodsec-skills): + - Process isolation: container or microVM per model + - JWT/OIDC on all inference endpoints; no unauthenticated access + - Model provenance: verify signatures before loading + - Scan models for embedded payloads (pickle, arbitrary code) + - Token lifecycle: short-lived, secure storage, revocation + - No direct filesystem access from inference process + - Resource limits to prevent DoS via large inputs + + # ── Agent security ─────────────────────────────────────────── + - path: "**/{agent,agents,agentic}/**/*" + instructions: | + Agent security (prodsec-skills): + - Unique, verifiable identity per agent instance + - Agent-to-agent auth: SPIFFE/mTLS, not shared secrets + - Agent-to-MCP auth: OAuth 2.1 client credentials flow + - No ambient authority; agents present credentials per call + - Audit trail for all inter-agent communication + + # ── LLM interaction ────────────────────────────────────────── + - path: "**/{llm,prompt,chat,completion}**/*" + instructions: | + LLM security (prodsec-skills): + - Prompt injection: separate system/user content; never + interpolate untrusted input into system prompts + - Output filtering: validate LLM output before execution + - File protection: restrict file access to declared paths + - Third-party models: evaluate trust, scan artifacts + - Guardrails: bidirectional filtering on prompts and responses + + # ── Supply chain & dependencies ────────────────────────────── + - path: "**/{requirements*.txt,Pipfile*,pyproject.toml,package*.json,go.mod,go.sum,Cargo.toml,Gemfile*,pom.xml,build.gradle*}" + instructions: | + Supply chain security (prodsec-skills): + - New deps: justify need, check license compatibility + - Pin exact versions; verify hashes where supported + - Flag known CVEs (cross-ref osv.dev) + - No pre-release or yanked versions in production + - SBOM: ensure build produces provenance attestations + - Signing: artifacts signed with Sigstore/cosign + + # ── CI/CD & GitHub Actions ─────────────────────────────────── + - path: ".github/workflows/**/*" + instructions: | + CI/CD security (prodsec-skills): + - Pin actions by full SHA, not tag + - No secrets in logs; mask sensitive outputs + - Least privilege: minimize GITHUB_TOKEN permissions + - No pull_request_target with checkout of PR head + - SAST/SCA steps in pipeline + - Sign artifacts with Sigstore/cosign + - Agentic CI actions: audit for prompt injection via + issue/PR title/body flowing into LLM prompts + + # ── Authentication & OAuth ─────────────────────────────────── + - path: "**/{auth,oauth,oidc,login,session,saml}/**/*" + instructions: | + Authentication review (prodsec-skills): + - OAuth 2.1: PKCE required; no implicit grant + - JWT: verify signature, issuer, audience, expiry, nbf + - Sessions: secure cookie flags, regenerate ID on login + - Passwords: Argon2id; never plaintext or weak hashes + - Rate limit login attempts; account lockout policy + - MFA: support and encourage; never bypass silently + - Service-to-service: SPIFFE/mTLS, not shared secrets + - Avoid API keys; prefer IdP-issued short-lived tokens + + # ── API gateway & rate limiting ────────────────────────────── + - path: "**/{gateway,proxy,ingress,route}/**/*" + instructions: | + API gateway review (prodsec-skills): + - Auth enforcement at gateway, not just downstream + - Rate limiting per client/endpoint; fail closed + - Request validation: size limits, content-type checks + - No internal-only routes exposed externally + - TLS termination with strong cipher suites + + # ── Go ─────────────────────────────────────────────────────── + - path: "**/*.go" + instructions: | + Go security (prodsec-skills): + - Never ignore error returns + - database/sql with placeholders; no fmt.Sprintf in queries + - Use stdlib crypto/* and golang.org/x/crypto (Go team maintained); + avoid third-party crypto libraries + - Integer overflow: bounds-check user-supplied sizes + - context.Context for cancellation and timeouts + + # ── C/C++ ──────────────────────────────────────────────────── + - path: "**/*.{c,cpp,cc,h,hpp}" + instructions: | + C/C++ security (prodsec-skills): + - Banned: gets, sprintf, strcpy, strcat, strtok + - Use strlcpy, snprintf, bounded APIs + - Compile: -fstack-protector-strong -fPIE -pie + -D_FORTIFY_SOURCE=2 -Wformat-security + - Nullify pointers after free; no use-after-free + - Integer overflow: check arithmetic on untrusted sizes + + # ── Database & external data ───────────────────────────────── + - path: "**/{db,database,redis,cache,storage}/**/*" + instructions: | + Data store security (prodsec-skills): + - Auth: no default credentials; use IAM or IdP tokens + - Encryption: TLS in transit, encryption at rest + - Least privilege: app user has minimal grants + - Redis/ElastiCache: AUTH required, no KEYS in prod, + rename dangerous commands (FLUSHALL, CONFIG) + - Connection strings: no embedded credentials + + # ── Messaging ──────────────────────────────────────────────── + - path: "**/{kafka,amq,mqtt,messaging,broker}/**/*" + instructions: | + Messaging security (prodsec-skills): + - Kafka/AMQ: TLS, SASL auth, per-topic ACLs + - MQTT: auth required, topic ACLs, payload encryption + - No anonymous access in production + + # ── Model registry ─────────────────────────────────────────── + - path: "**/{model_registry,model-registry,registry}/**/*" + instructions: | + Model registry review (prodsec-skills): + - Admin interface: auth + RBAC, no public exposure + - Model scanning: check for malicious payloads before publish + - Model signing: verify signatures on pull + - Audit logging: who uploaded/downloaded/deleted what + - Secure storage: encrypted at rest, access-controlled + + # Prodsec recommended security scanners + # https://github.com/RedHatProductSecurity/prodsec-skills/blob/main/.coderabbit.yaml + tools: + gitleaks: + enabled: true + semgrep: + enabled: true + checkov: + enabled: true + hadolint: + enabled: true + trivy: + enabled: true + osvScanner: + enabled: true + actionlint: + enabled: true + ast-grep: + essential_rules: true + +# Prodsec recommended knowledge base +# https://github.com/RedHatProductSecurity/prodsec-skills/blob/main/.coderabbit.yaml +knowledge_base: + code_guidelines: + enabled: true + filePatterns: + - "**/AGENTS.md" + - "**/REDHAT.md" + - "**/CLAUDE.md" + - "**/CONTRIBUTING.md" + issues: + scope: "auto" + pull_requests: + scope: "auto" + chat: - auto_reply: false + auto_reply: true + art: false From c977cecb18e3905ac1d610438aa37b1411881a11 Mon Sep 17 00:00:00 2001 From: Ondrej Metelka Date: Tue, 26 May 2026 14:19:40 +0200 Subject: [PATCH 4/5] Tune CodeRabbit config: reduce noise, add useful features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Noise reduction — disable defaults that add clutter without value: - in_progress_fortune, suggested_labels, suggested_reviewers, estimate_code_review_effort, related_prs - finishing_touches for docstrings and unit_tests (prevents CodeRabbit from opening follow-up PRs) Useful additions: - language: en-US, early_access: true - tone_instructions: direct and concise, focus on bugs/security - high_level_summary_in_walkthrough: true - enable_prompt_for_ai_agents: true (AI-friendly inline prompts) - knowledge_base.jira: auto (cross-reference Jira issues) - knowledge_base.linked_repositories: sandbox repo for cross-repo dependency awareness - tools: shellcheck, golangci-lint, yamllint (language-specific linters) Co-authored-by: Cursor --- .coderabbit.yaml | 50 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/.coderabbit.yaml b/.coderabbit.yaml index 98ab7bd0..8252ceaf 100644 --- a/.coderabbit.yaml +++ b/.coderabbit.yaml @@ -1,10 +1,14 @@ # CodeRabbit configuration — lightspeed-agentic-operator -# Docs: https://docs.coderabbit.ai/guides/configure-coderabbit +# Docs: https://docs.coderabbit.ai/reference/configuration +language: "en-US" +early_access: true +tone_instructions: >- + Be direct and concise. Focus on bugs, security issues, and correctness. + Skip praise and pleasantries. + reviews: - # Profile: "chill" generates fewer comments, focuses on significant issues profile: chill - # Auto-review settings auto_review: enabled: true base_branches: @@ -23,21 +27,31 @@ reviews: - '!api/go.sum' - '!vendor/**' # Prodsec recommended exclusions - # https://github.com/RedHatProductSecurity/prodsec-skills/blob/main/.coderabbit.yaml - '!node_modules/**' - '!dist/**' - '!*.min.js' - '!yarn.lock' - # Review behavior - collapse_walkthrough: true - poem: false + # Review output — keep signal, kill noise high_level_summary: true + high_level_summary_in_walkthrough: true + collapse_walkthrough: true review_status: true commit_status: true - - # Sequence diagrams for complex logic (chill profile limits these to significant changes) sequence_diagrams: true + poem: false + in_progress_fortune: false + suggested_labels: false + suggested_reviewers: false + estimate_code_review_effort: false + related_prs: false + enable_prompt_for_ai_agents: true + + finishing_touches: + docstrings: + enabled: false + unit_tests: + enabled: false # Prodsec recommended review instructions # https://github.com/RedHatProductSecurity/prodsec-skills/blob/main/.coderabbit.yaml @@ -320,8 +334,7 @@ reviews: - Audit logging: who uploaded/downloaded/deleted what - Secure storage: encrypted at rest, access-controlled - # Prodsec recommended security scanners - # https://github.com/RedHatProductSecurity/prodsec-skills/blob/main/.coderabbit.yaml + # Security scanners (prodsec) + language-specific linters tools: gitleaks: enabled: true @@ -339,9 +352,13 @@ reviews: enabled: true ast-grep: essential_rules: true + shellcheck: + enabled: true + golangci-lint: + enabled: true + yamllint: + enabled: true -# Prodsec recommended knowledge base -# https://github.com/RedHatProductSecurity/prodsec-skills/blob/main/.coderabbit.yaml knowledge_base: code_guidelines: enabled: true @@ -352,8 +369,15 @@ knowledge_base: - "**/CONTRIBUTING.md" issues: scope: "auto" + jira: + usage: "auto" pull_requests: scope: "auto" + linked_repositories: + - repository: "openshift/lightspeed-agentic-sandbox" + instructions: >- + Python/FastAPI agent runtime. The operator calls its + POST /v1/agent/run endpoint to run agent steps. chat: auto_reply: true From c14af6a846ec15b5b6365efefce3b1eb214f9320 Mon Sep 17 00:00:00 2001 From: Ondrej Metelka Date: Tue, 26 May 2026 14:22:40 +0200 Subject: [PATCH 5/5] Fix review comments: recursive globs, add Cargo.lock - Use recursive glob patterns (**/node_modules/**, **/dist/**, **/*.min.js, **/yarn.lock) so nested projects are covered - Add Cargo.lock to the supply-chain path_instructions glob alongside Cargo.toml for consistency Co-authored-by: Cursor --- .coderabbit.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.coderabbit.yaml b/.coderabbit.yaml index 8252ceaf..6e0f0157 100644 --- a/.coderabbit.yaml +++ b/.coderabbit.yaml @@ -27,10 +27,10 @@ reviews: - '!api/go.sum' - '!vendor/**' # Prodsec recommended exclusions - - '!node_modules/**' - - '!dist/**' - - '!*.min.js' - - '!yarn.lock' + - '!**/node_modules/**' + - '!**/dist/**' + - '!**/*.min.js' + - '!**/yarn.lock' # Review output — keep signal, kill noise high_level_summary: true @@ -237,7 +237,7 @@ reviews: - Guardrails: bidirectional filtering on prompts and responses # ── Supply chain & dependencies ────────────────────────────── - - path: "**/{requirements*.txt,Pipfile*,pyproject.toml,package*.json,go.mod,go.sum,Cargo.toml,Gemfile*,pom.xml,build.gradle*}" + - path: "**/{requirements*.txt,Pipfile*,pyproject.toml,package*.json,go.mod,go.sum,Cargo.toml,Cargo.lock,Gemfile*,pom.xml,build.gradle*}" instructions: | Supply chain security (prodsec-skills): - New deps: justify need, check license compatibility