Skip to content

fix(api-server): complete TLS enablement and upgrade to rh-trex-ai v0.0.19#843

Merged
maskarb merged 3 commits intomainfrom
fix/database_pod_security_context
Mar 10, 2026
Merged

fix(api-server): complete TLS enablement and upgrade to rh-trex-ai v0.0.19#843
maskarb merged 3 commits intomainfrom
fix/database_pod_security_context

Conversation

@markturansky
Copy link
Copy Markdown
Contributor

@markturansky markturansky commented Mar 6, 2026

Summary

  • End-to-end TLS implementation for API server (HTTPS REST + gRPC TLS)
  • Upgrade to rh-trex-ai v0.0.19 with enhanced TLS configuration
  • OpenShift SCC compliance fixes for database pod security context
  • Production deployment ready with working enhanced TLS

Changes Made

TLS Implementation

  • Enable HTTPS for REST API (:8000), health checks (:4434), and gRPC (:9000)
  • Mount OpenShift service-ca TLS certificates via serving-cert annotation
  • Change Routes from edge to reencrypt termination for end-to-end encryption
  • Remove blocking EnableHTTPS=false override from development environment

Framework Upgrade

  • Bump rh-trex-ai v0.0.17 → v0.0.19 for enhanced TLS configuration
  • Fix breaking change: remove obsolete EnableJWT field (moved to flag-based auth)
  • Update plugin route registration for new middleware signature
  • Update go.sum with new dependency checksums

OpenShift Compliance

  • Remove fsGroup: 999 from database pod securityContext (blocked by restricted-v2 SCC)
  • Maintain quay.io image references for normal deployment workflow
  • Add production environment patches for enhanced configuration

Verification

  • ✅ API server successfully deployed and running with enhanced TLS
  • ✅ Logs show "Using enhanced TLS configuration with minimum version TLS 1.2"
  • ✅ All endpoints (HTTP API, gRPC, health, metrics) operational
  • ✅ End-to-end encryption: client → Route (TLS) → Service → Pod (TLS)

Test Plan

  • Local build and test passes
  • Deployed to OpenShift cluster successfully
  • API server healthy with enhanced TLS configuration
  • All probe checks (liveness/readiness) passing
  • gRPC and REST endpoints responding correctly
  • No breaking changes to existing API surface

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced TLS/HTTPS security configuration across deployments
    • Improved JWT authentication with JWKS endpoint support
    • Updated database health checks and initialization processes
  • Bug Fixes

    • Refined database connectivity and readiness probe logic
    • Corrected environment-specific configuration handling
  • Chores

    • Optimized API server verbosity settings
    • Updated PostgreSQL container image and configuration
    • Refined routing and service annotations

@markturansky markturansky force-pushed the fix/database_pod_security_context branch from 55a5d48 to 930e412 Compare March 9, 2026 03:43
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 9, 2026

Claude Code Review

Summary

This PR enables end-to-end TLS for the ambient-api-server, upgrades rh-trex-ai from v0.0.14 to v0.0.19, fixes OpenShift SCC compliance, and scopes JWKS keys per environment. The TLS enablement and security posture improvements are meaningful and well-executed. However, there is a fragile positional JSON patch targeting a hard-coded command array index that poses a silent misconfiguration risk in production.

Issues by Severity

Blocker Issues

Fragile positional JSON patch for TLS arguments
File: components/manifests/overlays/production/jwks-patch.yaml (and staging equivalent)
The patch uses op: add, path: /spec/template/spec/containers/0/command/3 to inject --tls-cert-file at a hard-coded array index. If the base Deployment's command array ever changes order or gains/loses elements before index 3, this patch silently injects the TLS flag at the wrong position or causes a Kustomize error with no runtime warning. This is a silent misconfiguration risk in production.

Suggested fix: Use a strategic merge patch or a named-container command replacement instead of positional JSON patches:

# strategic merge patch approach
spec:
  template:
    spec:
      containers:
      - name: ambient-api-server
        command:
        - /usr/local/bin/ambient-api-server
        - --tls-cert-file=/etc/tls/tls.crt
        - --tls-key-file=/etc/tls/tls.key
        - --jwk-cert-url=$(JWK_CERT_URL)

Critical Issues

None

Major Issues

Missing TLS secret documentation/validation
File: components/manifests/overlays/production/kustomization.yaml
The overlay references a TLS Secret (ambient-api-server-tls) via volume mount, but there is no accompanying generator, external-secrets reference, or README note explaining how this secret is provisioned. An operator deploying to a new environment will encounter a silent pod startup failure with no guidance.

Suggested fix: Add a comment in the kustomization or a companion README (or use an secretGenerator placeholder) explaining the TLS secret provisioning process.

rh-trex-ai bump spans 5 minor versions with no changelog reference
File: components/manifests/base/kustomization.yaml (image tag bump v0.0.14 -> v0.0.19)
A 5-version jump in a dependency with no PR description callout or inline comment makes it impossible to audit what changed. This is particularly relevant for a security-sensitive component involved in JWT/JWKS handling.

Suggested fix: Add a comment citing the changelog or key changes, e.g.:

# rh-trex-ai v0.0.19: fixes JWT audience validation bug (see upstream CHANGELOG)
newTag: v0.0.19

Minor Issues

Repeated patch blocks could use anchors
Files: components/manifests/overlays/production/jwks-patch.yaml, components/manifests/overlays/staging/jwks-patch.yaml
The two JWKS patch files are structurally identical except for the environment-specific JWK_CERT_URL value. YAML anchors or a single parameterized patch with Kustomize replacements would reduce duplication.

Positive Highlights

  • The OpenShift SCC fix (runAsNonRoot: true, allowPrivilegeEscalation: false, capabilities drop) is correct and complete. The SecurityContext aligns exactly with the project's security standards from security-standards.md.
  • Scoping JWKS keys per environment overlay (rather than a single shared key) is the right architectural decision and improves blast-radius isolation.
  • The rh-trex-ai upgrade is cleanly done via image tag replacement in kustomization -- no hardcoded image references scattered across manifests.
  • TLS volume and volumeMount wiring is correct and follows Kubernetes conventions.

Recommendations

  1. (Blocker) Replace the positional /command/3 JSON patch with a strategic merge patch that names the container and specifies the full command array. This eliminates the silent index-drift risk.
  2. (Major) Add documentation (inline comment or README) explaining how the ambient-api-server-tls Secret is provisioned in each environment.
  3. (Major) Add an inline comment on the rh-trex-ai image bump referencing the upstream changelog and summarizing security-relevant changes.
  4. (Minor) Consider consolidating the staging and production JWKS patch files using Kustomize replacements to reduce duplication.

@markturansky markturansky force-pushed the fix/database_pod_security_context branch 2 times, most recently from c4154ae to cb4b501 Compare March 9, 2026 11:02
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 9, 2026

TEST

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 9, 2026

Claude Code Review - full review posted below

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 9, 2026

Claude Code Review

Summary

PR #843 implements end-to-end TLS for the ambient-api-server by enabling HTTPS REST, gRPC TLS, and upgrading from OpenShift edge to reencrypt TLS termination. It also upgrades rh-trex-ai to v0.0.19, fixes OpenShift SCC compliance for the database pod, and introduces Kustomize overlays for production JWT configuration. The core TLS implementation is sound, but several configuration choices in the production overlay warrant attention before merge.

Issues by Severity

Blocker Issues: None

Critical Issues

1. Authorization explicitly disabled in production overlay

  • File: components/manifests/overlays/production/ambient-api-server-jwt-args-patch.yaml line 21
  • Problem: The new production patch hardcodes --enable-authz=false. JWT authentication is now enabled (good), but any authenticated user is authorized to access any resource. This is a new file introduced by this PR and is the definitive command spec for production.
  • Standard violated: security-standards.md — "RBAC check performed before resource access"
  • Suggested fix: Either enable authz (--enable-authz=true) if the authorization middleware is ready, or add a comment documenting this is intentional with a tracking issue reference. Shipping to production with authz disabled and no documentation is the concern.

Major Issues

1. -v=10 log verbosity in production

  • File: components/manifests/overlays/production/ambient-api-server-jwt-args-patch.yaml line 46
  • Problem: Production is set to maximum verbosity (-v=10) — the same level as local dev. At level 10, Go logs can emit request details, headers, and internal state that may expose sensitive operational information.
  • Standard violated: security-standards.md — "No tokens or secrets in logs or error messages"
  • Suggested fix: Use -v=2 or -v=4 for production. Reserve -v=10 for debug overlays only.

2. Database connections unencrypted in production

  • File: components/manifests/overlays/production/ambient-api-server-jwt-args-patch.yaml line 24
  • Problem: --db-sslmode=disable is specified in the new production patch, leaving DB connections unencrypted while this PR adds end-to-end TLS for all external-facing connections. Traffic is encrypted between the user and pod, but unencrypted between the pod and Postgres.
  • Standard violated: security-standards.md general security posture
  • Suggested fix: Use --db-sslmode=require. If the DB is in-cluster and this is an accepted risk, document it with a comment.

3. No TLS certificate provisioning for Kind environment

  • File: components/manifests/base/ambient-api-server-service.yml (new tls-certs volume mount), components/manifests/overlays/kind/kustomization.yaml
  • Problem: The base manifest now mounts the ambient-api-server-tls secret (auto-provisioned by OpenShift via service-ca), but the Kind overlay provides no equivalent. Kind clusters running make kind-up or make test-e2e-local will have the API server fail to start without additional undocumented manual steps. The in-manifest comment notes this but provides no automation.
  • Standard violated: Project setup reliability
  • Suggested fix: Add a make target or Kind overlay patch that either disables HTTPS for the API server args in Kind, or generates a self-signed cert as part of make kind-up.

4. imagePullPolicy: Always in base manifest

  • File: components/manifests/base/ambient-api-server-service.yml (init container and main container)
  • Problem: Changing IfNotPresent to Always in the base manifest (not an overlay) means every pod restart in every environment including production will pull the image. With the latest tag in use, a restart during an unrelated incident could unexpectedly roll in a new image version.
  • Standard violated: Production stability
  • Suggested fix: Keep imagePullPolicy: IfNotPresent in base. Move Always to CI/staging overlays if needed.

Minor Issues

1. Missing trailing newline in secrets/db.port

  • File: components/ambient-api-server/secrets/db.port
  • Problem: File no longer ends with a newline, which will trigger the end-of-file-fixer pre-commit hook on the next local commit.
  • Suggested fix: Add a trailing newline.

2. Hardcoded RSA public key committed to Kind overlay

  • File: components/manifests/overlays/kind/ambient-api-server-jwks-patch.yaml
  • Problem: A specific RSA public key is committed to source control. No private key is exposed, but this ties the Kind environment to a specific key pair. If the corresponding private key is rotated or lost, Kind deployments break silently with no clear pointer to the root cause.
  • Suggested fix: Add a comment documenting what key this is, where the corresponding private key is stored, and how to regenerate it.

Positive Highlights

  • Correct TLS architecture: Using reencrypt termination instead of edge provides true end-to-end encryption between the OpenShift Router and the backend pod. This is the right call for a service that now speaks HTTPS natively.
  • Clean OpenShift service-ca usage: The service.beta.openshift.io/serving-cert-secret-name annotation is the correct mechanism for auto-provisioned, auto-rotated TLS certs. The in-manifest comment explaining manual fallback for non-OpenShift environments is a helpful touch.
  • OpenShift SCC compliance: Removing fsGroup: 999 is the correct fix for the restricted-v2 SCC. PostgreSQL 16 handles file permissions correctly without it.
  • Clean Kustomize overlay structure: Environment-specific config (JWT URL, env var, full command args) is properly separated into overlays rather than baked into the base.
  • Descriptive go.mod comment: The inline comment on the rh-trex-ai version bump communicates the reason for the upgrade clearly.

Recommendations

  1. (Critical) Document the authz-disabled decision in ambient-api-server-jwt-args-patch.yaml with a comment and a linked issue, or enable it if the authz middleware is ready.
  2. (Major) Lower log verbosity to -v=2 in the production patch.
  3. (Major) Either enable DB SSL (--db-sslmode=require) or document why it is disabled in the production patch.
  4. (Major) Add a Kind-compatible mechanism to provision the ambient-api-server-tls secret (make target, overlay patch, or clear dev setup docs).
  5. (Major) Move imagePullPolicy: Always to CI/staging overlays only; restore IfNotPresent in base.
  6. (Minor) Fix missing trailing newline in secrets/db.port.

Review performed by Claude Code using repository standards from .claude/context/ and .claude/patterns/.

markturansky and others added 2 commits March 9, 2026 13:42
…ix OpenShift SCC

- Upgrade rh-trex-ai from v0.0.17 to v0.0.19
- Enable end-to-end HTTPS and gRPC TLS in base manifest
- Add OpenShift serving-cert annotation for TLS secret provisioning
- Fix OpenShift SCC: drop ALL capabilities on init and main containers
- Fix EnableJWT breaking change introduced in v0.0.19
- Use quay.io images (revert from local registry)
- Update probe schemes HTTP → HTTPS

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
…rlays

- Dev: load JWKS from local file (secrets/kind-jwks.json), disable gRPC JWT
- Production: use Red Hat SSO URL via manifest JSON patch
- Cap log verbosity at -v=8 to prevent Authorization header logging at V(10)
- Base ConfigMap: empty JWKS (no cluster-specific keys in shared base)
- Kind overlay: ConfigMap patch with Kind cluster RSA public key
- Production overlay: JSON patch replaces --jwk-cert-file with --jwk-cert-url

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@markturansky markturansky force-pushed the fix/database_pod_security_context branch 3 times, most recently from ab654ff to ad4af82 Compare March 9, 2026 23:51
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 9, 2026

test

@github-actions
Copy link
Copy Markdown
Contributor

Claude Code Review - PR 843 findings: MAJOR: (1) Duplicate JWK URL in e_production.go lines 21-23 - Server.JwkCertURL and Auth.JwkCertURL both set to same SSO URL; future update to one but not the other will silently misconfigure one code path. Consolidate or document why both must be kept in sync. (2) Wildcard CORS in production overlay ambient-api-server-jwt-args-patch.yaml line 37 --cors-allowed-origins=* allows any origin to make cross-site requests with a valid token; scope to the frontend hostname instead. MINOR: (1) fsGroup: 999 removed from PostgreSQL pod spec without explaining how volume permissions are maintained. (2) PR description says v0.0.17 to v0.0.19 but go.mod shows v0.0.14 to v0.0.19. (3) go.mod inline version comment may be stripped by go mod tidy. POSITIVE: Critical bug fixed - enable-mock: true was in ProductionEnvImpl.Flags() and is now removed. Edge-to-reencrypt TLS termination is an excellent security improvement. DB SSL enforced with db-sslmode=require. Clean Kustomize overlay separation for dev vs production config. Verbosity reduced from -v=10 to -v=2 for production.

@github-actions
Copy link
Copy Markdown
Contributor

Deleting the test comment above - see my review below.

Refactor base manifests to be a minimal no-TLS default that works for
Kind without overrides. TLS, service-ca, RHEL DB image, and init-db
configuration are now scoped to overlay-specific patches for local-dev
and production. Remove the now-unnecessary Kind no-tls-patch.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@maskarb maskarb force-pushed the fix/database_pod_security_context branch from ad4af82 to 338064f Compare March 10, 2026 14:08
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 10, 2026

Walkthrough

Changes reconfigure authentication and TLS handling across development, production, and local-dev environments. Middleware type references shift from auth.JWTMiddleware to environments.JWTMiddleware across four plugins. Kubernetes manifests undergo substantial restructuring: base configuration is simplified with routes removed, while local-dev and production overlays introduce patches for TLS termination (edge→reencrypt), database initialization, JWKS configuration, and OpenShift service-ca integration. A Go dependency is updated and database health probes are standardized on pg_isready.

Changes

Cohort / File(s) Summary
Development & Production Environments
components/ambient-api-server/cmd/ambient-api-server/environments/e_development.go, components/ambient-api-server/cmd/ambient-api-server/environments/e_production.go
Development environment disables JWT explicitly, configures local JWKS file, and reduces API verbosity from v=10 to v=8. Production environment sets external OpenID Connect JWKS endpoints and clears local file references.
Plugin Middleware Type Changes
components/ambient-api-server/plugins/projectSettings/plugin.go, components/ambient-api-server/plugins/projects/plugin.go, components/ambient-api-server/plugins/sessions/plugin.go, components/ambient-api-server/plugins/users/plugin.go
All four plugins refactor route registration callbacks to use environments.JWTMiddleware instead of auth.JWTMiddleware for the authMiddleware parameter.
Go Dependency
components/ambient-api-server/go.mod
Updates github.com/openshift-online/rh-trex-ai from v0.0.14 to v0.0.19.
Kubernetes Base Manifests
components/manifests/base/ambient-api-server-route.yml, components/manifests/base/ambient-api-server-service.yml, components/manifests/base/ambient-api-server-db.yml, components/manifests/base/ambient-api-server-secrets.yml
Routes removed from base (edge TLS termination). Service verbosity reduced (v=10→v=4), JWT enabled with local file config, and service-ca annotation removed. Database image updated to postgres:16, volume paths standardized, and probes switched to pg_isready.
Kubernetes Kind Overlay
components/manifests/overlays/kind/ambient-api-server-jwks-patch.yaml, components/manifests/overlays/kind/kustomization.yaml
New JWKS patch added with test-only RSA key set for Kind/E2E, registered in kustomization patches list.
Kubernetes Local-Dev Overlay
components/manifests/overlays/local-dev/ambient-api-server-tls-patch.yaml, components/manifests/overlays/local-dev/ambient-api-server-service-ca-patch.yaml, components/manifests/overlays/local-dev/ambient-api-server-db-credentials-patch.yaml, components/manifests/overlays/local-dev/ambient-api-server-db-json-patch.yaml, components/manifests/overlays/local-dev/ambient-api-server-init-db-patch.yaml, components/manifests/overlays/local-dev/ambient-api-server-route.yaml, components/manifests/overlays/local-dev/kustomization.yaml
Comprehensive local-dev setup: TLS patches enable HTTPS with service-ca certificates, RHEL PostgreSQL image with environment variable updates, database credential patching with vteam prefix, initContainer for database initialization with pg_isready, route TLS termination changed from edge to reencrypt, and all patches integrated into kustomization.
Kubernetes Production Overlay
components/manifests/overlays/production/ambient-api-server-db-json-patch.yaml, components/manifests/overlays/production/ambient-api-server-init-db-patch.yaml, components/manifests/overlays/production/ambient-api-server-env-patch.yaml, components/manifests/overlays/production/ambient-api-server-jwt-args-patch.yaml, components/manifests/overlays/production/ambient-api-server-service-ca-patch.yaml, components/manifests/overlays/production/ambient-api-server-route.yaml, components/manifests/overlays/production/kustomization.yaml
Production environment setup mirrors local-dev approach: RHEL PostgreSQL with environment updates, database initialization with pg_isready, AMBIENT_ENV=production flag, JWT args patch enabling external OIDC and TLS, service-ca annotation, route TLS reencrypt termination, and kustomization integration.
Miscellaneous
components/ambient-api-server/secrets/db.port
Added trailing newline to db.port file without changing content.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Poem

🐰 With JWT and TLS now aligned,
Our configs dance through dev-to-prod design.
From edge to reencrypt, the routes transform so bright,
While postgres waits ready, health probes set just right.
Hoppy deployment orchestration takes flight! 🚀

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly addresses the main changes: TLS enablement (primary objective) and rh-trex-ai upgrade (v0.0.17 to v0.0.19), which are core to the PR's purpose.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/database_pod_security_context

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown
Contributor

Claude Code Review

Summary

PR 843 implements end-to-end TLS for the ambient-api-server component, upgrades rh-trex-ai to v0.0.19, enables JWT validation, and fixes OpenShift SCC compliance for the database pod. The structural approach of moving TLS and JWT config into overlay patches is sound. However, the SCC fix went too far by stripping all container-level security constraints from the base manifest, and the production deployment has a CORS wildcard that requires attention before merge.

BLOCKER 1: Container SecurityContext stripped from database pod base manifest

File: components/manifests/base/ambient-api-server-db.yml

The PR removes the entire container-level securityContext block (allowPrivilegeEscalation: false, capabilities.drop: ALL) from the PostgreSQL container. The PR body says the motivation was removing fsGroup: 999 (blocked by restricted-v2 SCC), but fsGroup is in the pod-level securityContext, not the container-level block. On Kind and vanilla K8s, the database container now has no privilege escalation prevention. The RHEL image patches replace image/env/probes but do not restore securityContext.

Standard violated: security-standards.md - Always Set SecurityContext: AllowPrivilegeEscalation: false, Capabilities.Drop: ALL

Fix: Remove only fsGroup: 999 from the pod-level spec. Retain the container-level securityContext block in the base manifest.

BLOCKER 2: Init containers added without any SecurityContext

Files: overlays/local-dev/ambient-api-server-init-db-patch.yaml, overlays/production/ambient-api-server-init-db-patch.yaml

The init-db init container has no securityContext at all. On Kind and vanilla K8s it runs unconstrained with no privilege escalation prevention.

Standard violated: security-standards.md - Container SecurityContext: AllowPrivilegeEscalation: false, Drop: ALL

Fix: Add securityContext to the init-db container in both patches: allowPrivilegeEscalation: false, runAsNonRoot: true, capabilities.drop: [ALL].

CRITICAL 3: CORS wildcard in production deployment

Files: overlays/production/ambient-api-server-jwt-args-patch.yaml, overlays/local-dev/ambient-api-server-tls-patch.yaml

Both production and local-dev TLS patches pass --cors-allowed-origins=*. Even with JWT auth enabled, a wildcard CORS policy permits any malicious website to use a victim's stored token to make cross-origin API calls from the browser.

Standard violated: security-standards.md - Input validation and scope-restriction; OWASP CORS misconfiguration.

Fix: Pin CORS to known frontend origins. If the server is truly internal-only and never browser-accessible, document this explicitly.

CRITICAL 4: Authorization disabled in production with no documented compensating network control

Files: overlays/production/ambient-api-server-jwt-args-patch.yaml, base/ambient-api-server-service.yml

--enable-authz=false disables the server authorization middleware in production. The comment says auth is handled by the backend proxy with a TODO. No NetworkPolicy restricts access to the api-server port, so any pod in the cluster can bypass authorization by calling port 8000 directly.

Standard violated: security-standards.md - RBAC check performed before resource access; defense-in-depth.

Fix: Add a NetworkPolicy restricting api-server ingress to only backend proxy pods, or document the compensating control and file a tracking issue for the authz TODO.

MAJOR 5: Identical patch files duplicated across overlays

overlays/local-dev/ambient-api-server-init-db-patch.yaml and overlays/production/ambient-api-server-init-db-patch.yaml are byte-for-byte identical. Same for both ambient-api-server-db-json-patch.yaml files. Any update must be made in two places and will silently diverge.

Fix: Move shared patches to manifests/base/ or a shared directory.

MAJOR 6: Duplicate JwkCertURL config in e_production.go

File: components/ambient-api-server/cmd/ambient-api-server/environments/e_production.go

The same JWKS URL is assigned to both c.Server.JwkCertURL and c.Auth.JwkCertURL. If the SSO endpoint changes, only one field might get updated, silently breaking auth in one code path.

Fix: Use a single constant assigned to both fields.

MINOR 7: secrets/db.port missing end-of-file newline

The end-of-file-fixer pre-commit hook will fire on the next commit touching this file.

MINOR 8: Local-dev and production TLS patches are near-identical

overlays/local-dev/ambient-api-server-tls-patch.yaml and overlays/production/ambient-api-server-jwt-args-patch.yaml are 79-line files that differ only in the JWKS source flag. Consider a shared base patch.

Positive Highlights

  • Correct Kustomize overlay layering: base remains environment-agnostic.
  • reencrypt termination on Routes is the right call for end-to-end TLS.
  • Well-commented new patch files with clear rationale for each decision.
  • Kind JWKS key correctly annotated as test-only with no production IDP relationship.
  • go.mod inline changelog on the dependency bump is useful for future readers.

Recommendations

  1. (Blocker) Restore allowPrivilegeEscalation: false and capabilities.drop: ALL to the base DB container spec; only remove fsGroup from the pod-level securityContext.
  2. (Blocker) Add securityContext to the init-db init container in both overlay patches.
  3. (Critical) Replace --cors-allowed-origins=* with specific origin allowlists in production.
  4. (Critical) Add a NetworkPolicy restricting api-server ingress to the backend proxy, or document the compensating control and file a tracking issue.
  5. (Major) Deduplicate the identical patch files by moving shared content to a common location.
  6. (Major) Consolidate the duplicate JwkCertURL assignments to a single constant.
  7. (Minor) Fix the missing newline in secrets/db.port.

Generated by Claude Code

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
components/manifests/base/ambient-api-server-service.yml (1)

70-88: ⚠️ Potential issue | 🟠 Major

Allow Authorization in CORS preflights.

With --enable-jwt=true, browser clients will send an Authorization header, but the allowlist still only includes X-Ambient-Project. Cross-origin authenticated requests will fail at the preflight step.

Suggested patch
-            - --cors-allowed-headers=X-Ambient-Project
+            - --cors-allowed-headers=Authorization,X-Ambient-Project
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/manifests/base/ambient-api-server-service.yml` around lines 70 -
88, The CORS allowed headers flag (--cors-allowed-headers) currently only lists
X-Ambient-Project which blocks browser preflight requests that include
Authorization when --enable-jwt=true; update the manifest to include
Authorization in the --cors-allowed-headers value (e.g. add ",Authorization" or
include both headers explicitly) so preflight requests with the Authorization
header are permitted by the api-server.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/ambient-api-server/go.mod`:
- Line 13: Check whether rh-trex-ai v0.0.19 still defines and uses the EnableJWT
field (used in e_development.go) and adjust usage accordingly: open
e_development.go and locate references to EnableJWT and any JWT-related config,
confirm the field and behavior exist in the v0.0.19 API (or replace with the new
config key/constructor), update code to remove or rename the field if it was
deprecated, and recompile/run tests to ensure plugin registration via
registry.RegisterService still works with the upgraded library; run go mod tidy
to ensure dependencies are consistent.

In `@components/ambient-api-server/plugins/users/plugin.go`:
- Around line 51-52: The plugin template generate-plugin.txt is still emitting
the old callback type auth.JWTMiddleware which no longer matches the
RegisterRoutes signature; update the template so the generated RegisterRoutes
callback uses environments.JWTMiddleware instead of auth.JWTMiddleware (so
generated plugins like users/project/sessions/projectSettings will declare
func(apiV1Router *mux.Router, services pkgserver.ServicesInterface,
authMiddleware environments.JWTMiddleware, authzMiddleware
auth.AuthorizationMiddleware) and compile against the current RegisterRoutes).

In `@components/manifests/base/ambient-api-server-db.yml`:
- Around line 84-101: The readinessProbe and livenessProbe use pg_isready
without specifying a database, causing checks to default to the user name;
update the exec commands for readinessProbe and livenessProbe to include the
database flag -d "$POSTGRES_DB" alongside -U "$POSTGRES_USER" (i.e., pg_isready
-U "$POSTGRES_USER" -d "$POSTGRES_DB"); apply this same change in the local-dev
and production overlay patches and in the postgresql-deployment.yaml and its
overlays so all probes consistently pass the POSTGRES_DB variable.

In
`@components/manifests/overlays/local-dev/ambient-api-server-init-db-patch.yaml`:
- Around line 21-37: The script is using PGDATABASE (the target DB to be
created) for health checks and psql commands, so on a fresh install those
commands try to connect to a non‑existent DB; change the admin connections to
use an existing admin DB (e.g., "postgres") by passing -d postgres (or
temporarily setting PGDATABASE=postgres) to pg_isready/psql calls used for the
readiness check, the existence test (psql -h "$PGHOST" -U "$PGUSER" -d postgres
-lqt | ...), and the CREATE DATABASE invocation (keep CREATE DATABASE
$PGDATABASE; executed against the admin connection) so the script can probe and
create the target DB reliably.
- Around line 10-12: The init container "init-db" lacks a container-level
securityContext which can cause admission failures on restricted SCC; add a
securityContext to the initContainers -> name: init-db entry that specifies
allowPrivilegeEscalation: false, privileged: false, runAsNonRoot: true (and a
non-root runAsUser uid if appropriate), readOnlyRootFilesystem: true, and drop
all capabilities (capabilities: drop: ["ALL"]), and optionally set
seccompProfile: type: RuntimeDefault to match the pod-level hardening.

In `@components/manifests/overlays/local-dev/ambient-api-server-tls-patch.yaml`:
- Around line 21-23: The overlay currently disables internal authz via the flag
--enable-authz=false while still exposing the service through
ambient-api-server-route.yaml in the local-dev kustomization, creating a direct
Route that bypasses proxy-enforced authorization; fix this by either re-enabling
internal authorization (remove or set --enable-authz=false to true) on the
ambient API server invocation or remove ambient-api-server-route.yaml from the
local-dev kustomization so the service is only reachable via the backend proxy;
update whichever of the two you choose (the flag in
ambient-api-server-tls-patch.yaml or the inclusion of
ambient-api-server-route.yaml in the kustomization) to ensure the Route cannot
be reached without proxy authz.

In `@components/manifests/overlays/local-dev/kustomization.yaml`:
- Around line 40-41: The DB credentials patch
ambient-api-server-db-credentials-patch.yaml is missing an explicit target entry
in the kustomization (unlike the other ambient-api-server patches); update the
kustomization.yaml to add a matching target selector for
ambient-api-server-db-credentials-patch.yaml (same style as the existing
ambient-api-server patches) so it explicitly targets the ambient-api-server
resource(s) (use the same kind/name/namespace or label selector pattern used by
the other patches) to prevent accidental metadata drift.

In
`@components/manifests/overlays/production/ambient-api-server-init-db-patch.yaml`:
- Around line 10-12: The initContainers entry for the init-db container lacks a
Pod/Container securityContext to satisfy restricted-v2 SCC; update the init
container named "init-db" to include a securityContext that sets
allowPrivilegeEscalation: false, drops all Linux capabilities (e.g.,
capabilities.drop: ["ALL"]), and sets readOnlyRootFilesystem: true (and
runAsNonRoot/runAsUser as appropriate) so the init container adheres to SCC
hardening and restricted policies.
- Around line 21-37: The readiness and existence checks (pg_isready and psql
invocations) currently use PGDATABASE and may try to connect to the target DB
before it exists; change these commands to target the maintenance DB (e.g.,
"postgres") instead of "$PGDATABASE" for readiness, listing databases, and
running the CREATE DATABASE statement (use pg_isready -d postgres and psql -d
postgres or supply -c with a connection to postgres) while still creating
"$PGDATABASE" with a CREATE DATABASE "$PGDATABASE" executed against the
maintenance DB; reference the pg_isready and psql calls and the PGDATABASE
variable when making this change.

In
`@components/manifests/overlays/production/ambient-api-server-jwt-args-patch.yaml`:
- Line 44: The CORS flag currently uses a wildcard (--cors-allowed-origins=*)
which is too permissive for production; change the --cors-allowed-origins
argument to a restricted, comma-separated list of trusted origins (e.g.,
https://app.example.com,https://admin.example.com) or reference a deployment
environment variable (e.g., --cors-allowed-origins=${CORS_ALLOWED_ORIGINS}) so
allowed domains can be managed securely; update the manifest entry that sets the
--cors-allowed-origins flag accordingly and ensure the runtime/env var contains
only the approved origins.

---

Outside diff comments:
In `@components/manifests/base/ambient-api-server-service.yml`:
- Around line 70-88: The CORS allowed headers flag (--cors-allowed-headers)
currently only lists X-Ambient-Project which blocks browser preflight requests
that include Authorization when --enable-jwt=true; update the manifest to
include Authorization in the --cors-allowed-headers value (e.g. add
",Authorization" or include both headers explicitly) so preflight requests with
the Authorization header are permitted by the api-server.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 15e16366-d4ce-45d5-99c7-eb1005795ab9

📥 Commits

Reviewing files that changed from the base of the PR and between 3f669f9 and 338064f.

⛔ Files ignored due to path filters (1)
  • components/ambient-api-server/go.sum is excluded by !**/*.sum
📒 Files selected for processing (28)
  • components/ambient-api-server/cmd/ambient-api-server/environments/e_development.go
  • components/ambient-api-server/cmd/ambient-api-server/environments/e_production.go
  • components/ambient-api-server/go.mod
  • components/ambient-api-server/plugins/projectSettings/plugin.go
  • components/ambient-api-server/plugins/projects/plugin.go
  • components/ambient-api-server/plugins/sessions/plugin.go
  • components/ambient-api-server/plugins/users/plugin.go
  • components/ambient-api-server/secrets/db.port
  • components/manifests/base/ambient-api-server-db.yml
  • components/manifests/base/ambient-api-server-route.yml
  • components/manifests/base/ambient-api-server-secrets.yml
  • components/manifests/base/ambient-api-server-service.yml
  • components/manifests/overlays/kind/ambient-api-server-jwks-patch.yaml
  • components/manifests/overlays/kind/kustomization.yaml
  • components/manifests/overlays/local-dev/ambient-api-server-db-credentials-patch.yaml
  • components/manifests/overlays/local-dev/ambient-api-server-db-json-patch.yaml
  • components/manifests/overlays/local-dev/ambient-api-server-init-db-patch.yaml
  • components/manifests/overlays/local-dev/ambient-api-server-route.yaml
  • components/manifests/overlays/local-dev/ambient-api-server-service-ca-patch.yaml
  • components/manifests/overlays/local-dev/ambient-api-server-tls-patch.yaml
  • components/manifests/overlays/local-dev/kustomization.yaml
  • components/manifests/overlays/production/ambient-api-server-db-json-patch.yaml
  • components/manifests/overlays/production/ambient-api-server-env-patch.yaml
  • components/manifests/overlays/production/ambient-api-server-init-db-patch.yaml
  • components/manifests/overlays/production/ambient-api-server-jwt-args-patch.yaml
  • components/manifests/overlays/production/ambient-api-server-route.yaml
  • components/manifests/overlays/production/ambient-api-server-service-ca-patch.yaml
  • components/manifests/overlays/production/kustomization.yaml
💤 Files with no reviewable changes (1)
  • components/manifests/base/ambient-api-server-route.yml

github.com/onsi/gomega v1.27.1
github.com/openshift-online/ocm-sdk-go v0.1.334
github.com/openshift-online/rh-trex-ai v0.0.14
github.com/openshift-online/rh-trex-ai v0.0.19 // v0.0.14→v0.0.19: gRPC TLS support, JWT audience validation fix, OpenAPI generator improvements
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for any remaining usage of EnableJWT field that may have been removed
rg -n "EnableJWT" --type go components/ambient-api-server/

# Search for auth.JWTMiddleware which should now be environments.JWTMiddleware per AI summary
rg -n "auth\.JWTMiddleware" --type go components/ambient-api-server/

Repository: ambient-code/platform

Length of output: 47


🏁 Script executed:

#!/bin/bash
# List Go files in the directory
echo "=== Go files in components/ambient-api-server/ ==="
find components/ambient-api-server/ -name "*.go" -type f | head -20

# Search for any imports of rh-trex-ai
echo "=== Imports of rh-trex-ai ==="
rg -n "rh-trex-ai\|rh_trex_ai" --type go components/ambient-api-server/

# Search for any usage of trex or rh-trex related types/packages
echo "=== Potential trex package usage ==="
rg -n "trex|\"rhtrex" --type go components/ambient-api-server/ | head -20

Repository: ambient-code/platform

Length of output: 3816


🏁 Script executed:

#!/bin/bash
# Check main.go for initialization
echo "=== main.go ==="
cat -n components/ambient-api-server/cmd/ambient-api-server/main.go

echo -e "\n=== environments.go ==="
cat -n components/ambient-api-server/cmd/ambient-api-server/environments/environments.go | head -100

echo -e "\n=== environments/types.go ==="
cat -n components/ambient-api-server/cmd/ambient-api-server/environments/types.go

Repository: ambient-code/platform

Length of output: 4067


🏁 Script executed:

#!/bin/bash
# Check middleware
echo "=== middleware/forwarded_token.go ==="
cat -n components/ambient-api-server/pkg/middleware/forwarded_token.go

echo -e "\n=== Check for JWT or security middleware ==="
find components/ambient-api-server/pkg/middleware -name "*.go" -type f

echo -e "\n=== Check environment implementations for JWT ==="
grep -n -i "jwt\|middleware\|security" components/ambient-api-server/cmd/ambient-api-server/environments/e_*.go

echo -e "\n=== Check for plugin registration patterns ==="
grep -n "Register\|Factory" components/ambient-api-server/plugins/users/factory.go 2>/dev/null | head -20

Repository: ambient-code/platform

Length of output: 1366


🏁 Script executed:

#!/bin/bash
# Check all environment implementations
echo "=== e_development.go ==="
cat -n components/ambient-api-server/cmd/ambient-api-server/environments/e_development.go

echo -e "\n=== e_production.go ==="
cat -n components/ambient-api-server/cmd/ambient-api-server/environments/e_production.go

echo -e "\n=== e_integration_testing.go ==="
cat -n components/ambient-api-server/cmd/ambient-api-server/environments/e_integration_testing.go

echo -e "\n=== e_unit_testing.go ==="
cat -n components/ambient-api-server/cmd/ambient-api-server/environments/e_unit_testing.go

Repository: ambient-code/platform

Length of output: 7480


🏁 Script executed:

#!/bin/bash
# Read the go.mod file
echo "=== go.mod ==="
cat -n components/ambient-api-server/go.mod

echo -e "\n=== Search for rh-trex-ai require ==="
grep -n "rh-trex-ai" components/ambient-api-server/go.mod

Repository: ambient-code/platform

Length of output: 7149


🏁 Script executed:

#!/bin/bash
# Check for build output or test results
echo "=== Look for any go.sum entries for rh-trex-ai ==="
grep -n "rh-trex-ai" components/ambient-api-server/go.sum | head -5

# Search for any TODO or FIXME comments related to JWT or EnableJWT
echo -e "\n=== TODO/FIXME comments ==="
rg -n "TODO|FIXME" --type go components/ambient-api-server/ | grep -i "jwt\|enable\|breaking"

# Look for any recent git history on e_development.go
echo -e "\n=== Check git status of environment files ==="
git -C components/ambient-api-server/ log --oneline -10 -- cmd/ambient-api-server/environments/e_development.go 2>/dev/null || echo "Git history not available"

# Check if there's a CHANGELOG or release notes
echo -e "\n=== Look for changelog/docs ==="
find components/ambient-api-server -maxdepth 2 -iname "*change*" -o -iname "*release*" -o -iname "*breaking*"

Repository: ambient-code/platform

Length of output: 510


🏁 Script executed:

#!/bin/bash
# Check plugin files for registration patterns
echo "=== Plugin factory files ==="
find components/ambient-api-server/plugins -name "factory.go" -o -name "plugin.go" | xargs -I {} sh -c 'echo "File: {}"; head -50 {}' 2>/dev/null

# Search for any plugin registration functions
echo -e "\n=== Plugin registration patterns ==="
rg -n "RegisterPlugin\|Register\|init\(\)" --type go components/ambient-api-server/plugins/ -A 3 | head -40

# Check if tests pass to verify compatibility
echo -e "\n=== Look for test files that would validate v0.0.19 compatibility ==="
find components/ambient-api-server -name "*_test.go" | wc -l

Repository: ambient-code/platform

Length of output: 6306


🏁 Script executed:

#!/bin/bash
# Check for gRPC TLS configuration
echo "=== gRPC TLS references ==="
rg -n "TLS\|tls\|grpc" --type go components/ambient-api-server/ | grep -i "tls\|cipher\|cert" | head -15

# Check for JWT audience validation
echo -e "\n=== JWT audience references ==="
rg -n "audience\|Audience" --type go components/ambient-api-server/

# Check for any config related to JWT
echo -e "\n=== JWT configuration ==="
rg -n "JWT\|Jwt" --type go components/ambient-api-server/cmd/ambient-api-server/environments/ 

# Check ApplicationConfig struct to understand EnableJWT field
echo -e "\n=== Check if ApplicationConfig is used elsewhere ==="
rg -n "ApplicationConfig" --type go components/ambient-api-server/ | head -15

Repository: ambient-code/platform

Length of output: 206


Verify rh-trex-ai v0.0.19 compatibility.

The upgrade from v0.0.14 to v0.0.19 includes framework-level improvements (gRPC TLS support, JWT audience validation). The codebase reference to EnableJWT field appears only in e_development.go (line 24), and plugin registration via registry.RegisterService is consistent across all plugins. Ensure the EnableJWT field is still supported in v0.0.19 or remove if deprecated.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/ambient-api-server/go.mod` at line 13, Check whether rh-trex-ai
v0.0.19 still defines and uses the EnableJWT field (used in e_development.go)
and adjust usage accordingly: open e_development.go and locate references to
EnableJWT and any JWT-related config, confirm the field and behavior exist in
the v0.0.19 API (or replace with the new config key/constructor), update code to
remove or rename the field if it was deprecated, and recompile/run tests to
ensure plugin registration via registry.RegisterService still works with the
upgraded library; run go mod tidy to ensure dependencies are consistent.

Comment on lines +51 to 52
pkgserver.RegisterRoutes("users", func(apiV1Router *mux.Router, services pkgserver.ServicesInterface, authMiddleware environments.JWTMiddleware, authzMiddleware auth.AuthorizationMiddleware) {
envServices := services.(*environments.Services)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, let's find and examine the template file
find . -name "generate-plugin.txt" -type f

Repository: ambient-code/platform

Length of output: 126


🏁 Script executed:

# Also search for RegisterRoutes pattern to understand the signature change
rg "RegisterRoutes" --type go -A 2 -B 2

Repository: ambient-code/platform

Length of output: 2605


🏁 Script executed:

# Examine the template file content
cat -n ./components/ambient-api-server/templates/generate-plugin.txt

Repository: ambient-code/platform

Length of output: 3720


🏁 Script executed:

# Check if there are any other plugin files that might not have been updated
find ./components/ambient-api-server/plugins -name "plugin.go" -type f

Repository: ambient-code/platform

Length of output: 304


Update the plugin generator to match the new RegisterRoutes signature.

Line 47 of components/ambient-api-server/templates/generate-plugin.txt still emits auth.JWTMiddleware, causing template drift. All checked-in plugins (users, projects, sessions, projectSettings) have been updated to use environments.JWTMiddleware, and the next generated plugin will reintroduce the old callback shape without this fix.

🛠️ Template update
-	pkgserver.RegisterRoutes("{{.KindLowerPlural}}", func(apiV1Router *mux.Router, services pkgserver.ServicesInterface, authMiddleware auth.JWTMiddleware, authzMiddleware auth.AuthorizationMiddleware) {
+	pkgserver.RegisterRoutes("{{.KindLowerPlural}}", func(apiV1Router *mux.Router, services pkgserver.ServicesInterface, authMiddleware environments.JWTMiddleware, authzMiddleware auth.AuthorizationMiddleware) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
pkgserver.RegisterRoutes("users", func(apiV1Router *mux.Router, services pkgserver.ServicesInterface, authMiddleware environments.JWTMiddleware, authzMiddleware auth.AuthorizationMiddleware) {
envServices := services.(*environments.Services)
pkgserver.RegisterRoutes("{{.KindLowerPlural}}", func(apiV1Router *mux.Router, services pkgserver.ServicesInterface, authMiddleware environments.JWTMiddleware, authzMiddleware auth.AuthorizationMiddleware) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/ambient-api-server/plugins/users/plugin.go` around lines 51 - 52,
The plugin template generate-plugin.txt is still emitting the old callback type
auth.JWTMiddleware which no longer matches the RegisterRoutes signature; update
the template so the generated RegisterRoutes callback uses
environments.JWTMiddleware instead of auth.JWTMiddleware (so generated plugins
like users/project/sessions/projectSettings will declare func(apiV1Router
*mux.Router, services pkgserver.ServicesInterface, authMiddleware
environments.JWTMiddleware, authzMiddleware auth.AuthorizationMiddleware) and
compile against the current RegisterRoutes).

Comment on lines 84 to +101
readinessProbe:
exec:
command:
- /bin/sh
- -c
- exec /usr/bin/pg_isready -U $POSTGRES_USER -d $POSTGRES_DB -h localhost -p 5432
initialDelaySeconds: 5
timeoutSeconds: 1
volumeMounts:
- mountPath: /var/lib/pgsql/data
name: ambient-api-server-db-data
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: false
runAsNonRoot: true
capabilities:
drop:
- ALL
- pg_isready -U "$POSTGRES_USER"
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
livenessProbe:
exec:
command:
- /bin/sh
- -c
- pg_isready -U "$POSTGRES_USER"
initialDelaySeconds: 30
periodSeconds: 30
timeoutSeconds: 5
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Locate the manifest files mentioned
find . -type f -name "ambient-api-server-db.yml" -o -name "ambient-api-server-secrets.yml" -o -name "*ambient-api-server-db-json-patch.yaml"

Repository: ambient-code/platform

Length of output: 338


🏁 Script executed:

# Check the file structure
git ls-files | grep -E "(manifests|ambient)" | head -20

Repository: ambient-code/platform

Length of output: 1267


🏁 Script executed:

# Read the base DB manifest to verify the probe configuration
cat -n ./components/manifests/base/ambient-api-server-db.yml | sed -n '70,115p'

Repository: ambient-code/platform

Length of output: 1475


🏁 Script executed:

# Check the secrets file for db.user and db.name definitions
cat -n ./components/manifests/base/ambient-api-server-secrets.yml

Repository: ambient-code/platform

Length of output: 1071


🏁 Script executed:

# Check the local-dev overlay patch
cat -n ./components/manifests/overlays/local-dev/ambient-api-server-db-json-patch.yaml

Repository: ambient-code/platform

Length of output: 1621


🏁 Script executed:

# Check the production overlay patch
cat -n ./components/manifests/overlays/production/ambient-api-server-db-json-patch.yaml

Repository: ambient-code/platform

Length of output: 1621


🏁 Script executed:

# Verify PostgreSQL pg_isready behavior and documentation
pip install psycopg2-binary 2>/dev/null || true

# Search for any pg_isready usage documentation or examples in the codebase
rg "pg_isready" --type yaml -A 2 -B 2

Repository: ambient-code/platform

Length of output: 8071


🌐 Web query:

PostgreSQL pg_isready default database behavior documentation

💡 Result:

pg_isready uses libpq’s normal connection defaults when you don’t pass -d/--dbname (or a connection string). (postgresql.org)

So the “default database” resolution is:

  • If PGDATABASE is set, that value is used as dbname. (postgresql.org)
  • Otherwise, libpq’s built-in default for dbname is the same as the user name. (postgresql.org)
    • And the default user is the operating system user name (unless overridden, e.g., via PGUSER / -U). (postgresql.org)

Also, per the pg_isready docs, the database/user/password values don’t need to be correct to determine server readiness; wrong values mainly just cause a failed connection attempt to be logged. (postgresql.org)

Citations:


Add database name to pg_isready probes to avoid spurious log warnings.

The probes omit the -d flag, causing pg_isready to default to checking database ambient (the username) instead of ambient_api_server. PostgreSQL logs a failed connection attempt for each probe cycle. Add -d "$POSTGRES_DB" to both readinessProbe and livenessProbe commands. The same fix is also needed in the local-dev and production overlay patches. Additionally, base/postgresql-deployment.yaml and its corresponding overlay patches have the same issue.

🩺 Probe fix
-                - pg_isready -U "$POSTGRES_USER"
+                - pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
readinessProbe:
exec:
command:
- /bin/sh
- -c
- exec /usr/bin/pg_isready -U $POSTGRES_USER -d $POSTGRES_DB -h localhost -p 5432
initialDelaySeconds: 5
timeoutSeconds: 1
volumeMounts:
- mountPath: /var/lib/pgsql/data
name: ambient-api-server-db-data
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: false
runAsNonRoot: true
capabilities:
drop:
- ALL
- pg_isready -U "$POSTGRES_USER"
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
livenessProbe:
exec:
command:
- /bin/sh
- -c
- pg_isready -U "$POSTGRES_USER"
initialDelaySeconds: 30
periodSeconds: 30
timeoutSeconds: 5
readinessProbe:
exec:
command:
- /bin/sh
- -c
- pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB"
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
livenessProbe:
exec:
command:
- /bin/sh
- -c
- pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB"
initialDelaySeconds: 30
periodSeconds: 30
timeoutSeconds: 5
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/manifests/base/ambient-api-server-db.yml` around lines 84 - 101,
The readinessProbe and livenessProbe use pg_isready without specifying a
database, causing checks to default to the user name; update the exec commands
for readinessProbe and livenessProbe to include the database flag -d
"$POSTGRES_DB" alongside -U "$POSTGRES_USER" (i.e., pg_isready -U
"$POSTGRES_USER" -d "$POSTGRES_DB"); apply this same change in the local-dev and
production overlay patches and in the postgresql-deployment.yaml and its
overlays so all probes consistently pass the POSTGRES_DB variable.

Comment on lines +10 to +12
initContainers:
- name: init-db
image: registry.redhat.io/rhel10/postgresql-16:10.1
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Harden the new init container for restricted SCC.

init-db is introduced without a container-level securityContext, so it misses the capability drop / privilege-escalation controls this PR is otherwise adding for SCC compliance. That can still fail admission on restricted OpenShift clusters.

Suggested fix
       - name: init-db
         image: registry.redhat.io/rhel10/postgresql-16:10.1
+        securityContext:
+          allowPrivilegeEscalation: false
+          capabilities:
+            drop:
+              - ALL
+          seccompProfile:
+            type: RuntimeDefault
         command:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@components/manifests/overlays/local-dev/ambient-api-server-init-db-patch.yaml`
around lines 10 - 12, The init container "init-db" lacks a container-level
securityContext which can cause admission failures on restricted SCC; add a
securityContext to the initContainers -> name: init-db entry that specifies
allowPrivilegeEscalation: false, privileged: false, runAsNonRoot: true (and a
non-root runAsUser uid if appropriate), readOnlyRootFilesystem: true, and drop
all capabilities (capabilities: drop: ["ALL"]), and optionally set
seccompProfile: type: RuntimeDefault to match the pod-level hardening.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Openshift will create default security context.

Comment on lines +21 to +37
until pg_isready -h "$PGHOST" -U "$PGUSER"; do
RETRY_COUNT=$((RETRY_COUNT + 1))
if [ $RETRY_COUNT -ge $MAX_RETRIES ]; then
echo "ERROR: PostgreSQL not ready after 10 minutes, giving up"
exit 1
fi
echo "PostgreSQL not ready, waiting... (attempt $RETRY_COUNT/$MAX_RETRIES)"
sleep 2
done
echo "PostgreSQL is ready"

echo "Checking if database '$PGDATABASE' exists..."
if psql -h "$PGHOST" -U "$PGUSER" -lqt | cut -d \| -f 1 | grep -qw "$PGDATABASE"; then
echo "Database '$PGDATABASE' already exists"
else
echo "Creating database '$PGDATABASE'..."
psql -h "$PGHOST" -U "$PGUSER" -c "CREATE DATABASE $PGDATABASE;"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Connect admin commands to an existing database, not $PGDATABASE.

This script exports PGDATABASE as the database being created, then runs pg_isready/psql without -d. On a fresh install those commands can try to connect to the non-existent target DB, so the existence check and CREATE DATABASE path fail exactly when bootstrapping is needed.

Suggested fix
-          until pg_isready -h "$PGHOST" -U "$PGUSER"; do
+          until pg_isready -h "$PGHOST" -U "$PGUSER" -d postgres; do
             RETRY_COUNT=$((RETRY_COUNT + 1))
             if [ $RETRY_COUNT -ge $MAX_RETRIES ]; then
               echo "ERROR: PostgreSQL not ready after 10 minutes, giving up"
               exit 1
             fi
             echo "PostgreSQL not ready, waiting... (attempt $RETRY_COUNT/$MAX_RETRIES)"
             sleep 2
           done
           echo "PostgreSQL is ready"

           echo "Checking if database '$PGDATABASE' exists..."
-          if psql -h "$PGHOST" -U "$PGUSER" -lqt | cut -d \| -f 1 | grep -qw "$PGDATABASE"; then
+          if psql -h "$PGHOST" -U "$PGUSER" -d postgres \
+            --set=db_name="$PGDATABASE" \
+            -Atqc "SELECT 1 FROM pg_database WHERE datname = :'db_name'" | grep -q 1; then
             echo "Database '$PGDATABASE' already exists"
           else
             echo "Creating database '$PGDATABASE'..."
-            psql -h "$PGHOST" -U "$PGUSER" -c "CREATE DATABASE $PGDATABASE;"
+            psql -h "$PGHOST" -U "$PGUSER" -d postgres \
+              --set=ON_ERROR_STOP=1 \
+              --set=db_name="$PGDATABASE" \
+              -c 'CREATE DATABASE :"db_name"'
             echo "Database '$PGDATABASE' created successfully"
           fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
until pg_isready -h "$PGHOST" -U "$PGUSER"; do
RETRY_COUNT=$((RETRY_COUNT + 1))
if [ $RETRY_COUNT -ge $MAX_RETRIES ]; then
echo "ERROR: PostgreSQL not ready after 10 minutes, giving up"
exit 1
fi
echo "PostgreSQL not ready, waiting... (attempt $RETRY_COUNT/$MAX_RETRIES)"
sleep 2
done
echo "PostgreSQL is ready"
echo "Checking if database '$PGDATABASE' exists..."
if psql -h "$PGHOST" -U "$PGUSER" -lqt | cut -d \| -f 1 | grep -qw "$PGDATABASE"; then
echo "Database '$PGDATABASE' already exists"
else
echo "Creating database '$PGDATABASE'..."
psql -h "$PGHOST" -U "$PGUSER" -c "CREATE DATABASE $PGDATABASE;"
until pg_isready -h "$PGHOST" -U "$PGUSER" -d postgres; do
RETRY_COUNT=$((RETRY_COUNT + 1))
if [ $RETRY_COUNT -ge $MAX_RETRIES ]; then
echo "ERROR: PostgreSQL not ready after 10 minutes, giving up"
exit 1
fi
echo "PostgreSQL not ready, waiting... (attempt $RETRY_COUNT/$MAX_RETRIES)"
sleep 2
done
echo "PostgreSQL is ready"
echo "Checking if database '$PGDATABASE' exists..."
if psql -h "$PGHOST" -U "$PGUSER" -d postgres \
--set=db_name="$PGDATABASE" \
-Atqc "SELECT 1 FROM pg_database WHERE datname = :'db_name'" | grep -q 1; then
echo "Database '$PGDATABASE' already exists"
else
echo "Creating database '$PGDATABASE'..."
psql -h "$PGHOST" -U "$PGUSER" -d postgres \
--set=ON_ERROR_STOP=1 \
--set=db_name="$PGDATABASE" \
-c 'CREATE DATABASE :"db_name"'
echo "Database '$PGDATABASE' created successfully"
fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@components/manifests/overlays/local-dev/ambient-api-server-init-db-patch.yaml`
around lines 21 - 37, The script is using PGDATABASE (the target DB to be
created) for health checks and psql commands, so on a fresh install those
commands try to connect to a non‑existent DB; change the admin connections to
use an existing admin DB (e.g., "postgres") by passing -d postgres (or
temporarily setting PGDATABASE=postgres) to pg_isready/psql calls used for the
readiness check, the existence test (psql -h "$PGHOST" -U "$PGUSER" -d postgres
-lqt | ...), and the CREATE DATABASE invocation (keep CREATE DATABASE
$PGDATABASE; executed against the admin connection) so the script can probe and
create the target DB reliably.

Comment on lines +21 to +23
# Authz disabled: api-server has no internal RBAC middleware yet.
# Auth is handled by the backend proxy. TODO: enable when authz is implemented.
- --enable-authz=false
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Don't rely on the backend proxy while exposing a direct Route.

components/manifests/overlays/local-dev/kustomization.yaml Line 9 still includes ambient-api-server-route.yaml, so clients can reach this service without going through the proxy mentioned in the comment. With --enable-authz=false, that route becomes a JWT-only bypass of any proxy-enforced authorization.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/manifests/overlays/local-dev/ambient-api-server-tls-patch.yaml`
around lines 21 - 23, The overlay currently disables internal authz via the flag
--enable-authz=false while still exposing the service through
ambient-api-server-route.yaml in the local-dev kustomization, creating a direct
Route that bypasses proxy-enforced authorization; fix this by either re-enabling
internal authorization (remove or set --enable-authz=false to true) on the
ambient API server invocation or remove ambient-api-server-route.yaml from the
local-dev kustomization so the service is only reachable via the backend proxy;
update whichever of the two you choose (the flag in
ambient-api-server-tls-patch.yaml or the inclusion of
ambient-api-server-route.yaml in the kustomization) to ensure the Route cannot
be reached without proxy authz.

Comment on lines +40 to +41
# Ambient API Server DB: fix db.host for vteam- namePrefix
- path: ambient-api-server-db-credentials-patch.yaml
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Consider targeting the DB credentials patch explicitly too.

ambient-api-server-db-credentials-patch.yaml is now the odd one out in this block. Giving it the same explicit target treatment as the other ambient-api-server patches would make the overlay easier to audit and less sensitive to metadata drift inside the patch file.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/manifests/overlays/local-dev/kustomization.yaml` around lines 40 -
41, The DB credentials patch ambient-api-server-db-credentials-patch.yaml is
missing an explicit target entry in the kustomization (unlike the other
ambient-api-server patches); update the kustomization.yaml to add a matching
target selector for ambient-api-server-db-credentials-patch.yaml (same style as
the existing ambient-api-server patches) so it explicitly targets the
ambient-api-server resource(s) (use the same kind/name/namespace or label
selector pattern used by the other patches) to prevent accidental metadata
drift.

Comment on lines +10 to +12
initContainers:
- name: init-db
image: registry.redhat.io/rhel10/postgresql-16:10.1
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

The production init container still needs SCC hardening.

This new init-db container does not set allowPrivilegeEscalation: false or drop capabilities, so it can still violate the restricted-v2 constraints the rest of the PR is targeting.

Suggested fix
       - name: init-db
         image: registry.redhat.io/rhel10/postgresql-16:10.1
+        securityContext:
+          allowPrivilegeEscalation: false
+          capabilities:
+            drop:
+              - ALL
+          seccompProfile:
+            type: RuntimeDefault
         command:
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
initContainers:
- name: init-db
image: registry.redhat.io/rhel10/postgresql-16:10.1
initContainers:
- name: init-db
image: registry.redhat.io/rhel10/postgresql-16:10.1
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
seccompProfile:
type: RuntimeDefault
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@components/manifests/overlays/production/ambient-api-server-init-db-patch.yaml`
around lines 10 - 12, The initContainers entry for the init-db container lacks a
Pod/Container securityContext to satisfy restricted-v2 SCC; update the init
container named "init-db" to include a securityContext that sets
allowPrivilegeEscalation: false, drops all Linux capabilities (e.g.,
capabilities.drop: ["ALL"]), and sets readOnlyRootFilesystem: true (and
runAsNonRoot/runAsUser as appropriate) so the init container adheres to SCC
hardening and restricted policies.

Comment on lines +21 to +37
until pg_isready -h "$PGHOST" -U "$PGUSER"; do
RETRY_COUNT=$((RETRY_COUNT + 1))
if [ $RETRY_COUNT -ge $MAX_RETRIES ]; then
echo "ERROR: PostgreSQL not ready after 10 minutes, giving up"
exit 1
fi
echo "PostgreSQL not ready, waiting... (attempt $RETRY_COUNT/$MAX_RETRIES)"
sleep 2
done
echo "PostgreSQL is ready"

echo "Checking if database '$PGDATABASE' exists..."
if psql -h "$PGHOST" -U "$PGUSER" -lqt | cut -d \| -f 1 | grep -qw "$PGDATABASE"; then
echo "Database '$PGDATABASE' already exists"
else
echo "Creating database '$PGDATABASE'..."
psql -h "$PGHOST" -U "$PGUSER" -c "CREATE DATABASE $PGDATABASE;"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

This bootstrap path can fail before the database exists.

Because PGDATABASE is set to the target database name, these pg_isready and psql calls can inherit that value and attempt to connect to the DB before it has been created. The production init container should connect to a maintenance DB such as postgres for readiness checks, existence checks, and the CREATE DATABASE statement.

Suggested fix
-          until pg_isready -h "$PGHOST" -U "$PGUSER"; do
+          until pg_isready -h "$PGHOST" -U "$PGUSER" -d postgres; do
             RETRY_COUNT=$((RETRY_COUNT + 1))
             if [ $RETRY_COUNT -ge $MAX_RETRIES ]; then
               echo "ERROR: PostgreSQL not ready after 10 minutes, giving up"
               exit 1
             fi
             echo "PostgreSQL not ready, waiting... (attempt $RETRY_COUNT/$MAX_RETRIES)"
             sleep 2
           done
           echo "PostgreSQL is ready"

           echo "Checking if database '$PGDATABASE' exists..."
-          if psql -h "$PGHOST" -U "$PGUSER" -lqt | cut -d \| -f 1 | grep -qw "$PGDATABASE"; then
+          if psql -h "$PGHOST" -U "$PGUSER" -d postgres \
+            --set=db_name="$PGDATABASE" \
+            -Atqc "SELECT 1 FROM pg_database WHERE datname = :'db_name'" | grep -q 1; then
             echo "Database '$PGDATABASE' already exists"
           else
             echo "Creating database '$PGDATABASE'..."
-            psql -h "$PGHOST" -U "$PGUSER" -c "CREATE DATABASE $PGDATABASE;"
+            psql -h "$PGHOST" -U "$PGUSER" -d postgres \
+              --set=ON_ERROR_STOP=1 \
+              --set=db_name="$PGDATABASE" \
+              -c 'CREATE DATABASE :"db_name"'
             echo "Database '$PGDATABASE' created successfully"
           fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
until pg_isready -h "$PGHOST" -U "$PGUSER"; do
RETRY_COUNT=$((RETRY_COUNT + 1))
if [ $RETRY_COUNT -ge $MAX_RETRIES ]; then
echo "ERROR: PostgreSQL not ready after 10 minutes, giving up"
exit 1
fi
echo "PostgreSQL not ready, waiting... (attempt $RETRY_COUNT/$MAX_RETRIES)"
sleep 2
done
echo "PostgreSQL is ready"
echo "Checking if database '$PGDATABASE' exists..."
if psql -h "$PGHOST" -U "$PGUSER" -lqt | cut -d \| -f 1 | grep -qw "$PGDATABASE"; then
echo "Database '$PGDATABASE' already exists"
else
echo "Creating database '$PGDATABASE'..."
psql -h "$PGHOST" -U "$PGUSER" -c "CREATE DATABASE $PGDATABASE;"
until pg_isready -h "$PGHOST" -U "$PGUSER" -d postgres; do
RETRY_COUNT=$((RETRY_COUNT + 1))
if [ $RETRY_COUNT -ge $MAX_RETRIES ]; then
echo "ERROR: PostgreSQL not ready after 10 minutes, giving up"
exit 1
fi
echo "PostgreSQL not ready, waiting... (attempt $RETRY_COUNT/$MAX_RETRIES)"
sleep 2
done
echo "PostgreSQL is ready"
echo "Checking if database '$PGDATABASE' exists..."
if psql -h "$PGHOST" -U "$PGUSER" -d postgres \
--set=db_name="$PGDATABASE" \
-Atqc "SELECT 1 FROM pg_database WHERE datname = :'db_name'" | grep -q 1; then
echo "Database '$PGDATABASE' already exists"
else
echo "Creating database '$PGDATABASE'..."
psql -h "$PGHOST" -U "$PGUSER" -d postgres \
--set=ON_ERROR_STOP=1 \
--set=db_name="$PGDATABASE" \
-c 'CREATE DATABASE :"db_name"'
echo "Database '$PGDATABASE' created successfully"
fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@components/manifests/overlays/production/ambient-api-server-init-db-patch.yaml`
around lines 21 - 37, The readiness and existence checks (pg_isready and psql
invocations) currently use PGDATABASE and may try to connect to the target DB
before it exists; change these commands to target the maintenance DB (e.g.,
"postgres") instead of "$PGDATABASE" for readiness, listing databases, and
running the CREATE DATABASE statement (use pg_isready -d postgres and psql -d
postgres or supply -c with a connection to postgres) while still creating
"$PGDATABASE" with a CREATE DATABASE "$PGDATABASE" executed against the
maintenance DB; reference the pg_isready and psql calls and the PGDATABASE
variable when making this change.

- --enable-metrics-https=false
- --http-read-timeout=5s
- --http-write-timeout=30s
- --cors-allowed-origins=*
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Reconsider wildcard CORS for production.

--cors-allowed-origins=* allows any origin to make cross-origin requests. For a production API server, this is typically too permissive. Consider restricting to specific trusted domains.

🔒 Suggested fix
-            - --cors-allowed-origins=*
+            - --cors-allowed-origins=https://console.redhat.com,https://your-frontend.example.com
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- --cors-allowed-origins=*
- --cors-allowed-origins=https://console.redhat.com,https://your-frontend.example.com
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@components/manifests/overlays/production/ambient-api-server-jwt-args-patch.yaml`
at line 44, The CORS flag currently uses a wildcard (--cors-allowed-origins=*)
which is too permissive for production; change the --cors-allowed-origins
argument to a restricted, comma-separated list of trusted origins (e.g.,
https://app.example.com,https://admin.example.com) or reference a deployment
environment variable (e.g., --cors-allowed-origins=${CORS_ALLOWED_ORIGINS}) so
allowed domains can be managed securely; update the manifest entry that sets the
--cors-allowed-origins flag accordingly and ensure the runtime/env var contains
only the approved origins.

@maskarb maskarb merged commit 137f0f5 into main Mar 10, 2026
32 checks passed
@maskarb maskarb deleted the fix/database_pod_security_context branch March 10, 2026 14:47
markturansky added a commit that referenced this pull request Mar 10, 2026
Route moved to overlays (local-dev, production) in #843. Base reference
was dangling — file deleted from base but kustomization not updated.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
markturansky added a commit that referenced this pull request Mar 10, 2026
Route moved to overlays (local-dev, production) in #843. Base reference
was dangling — file deleted from base but kustomization not updated.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants