Skip to content

Commit a1e211e

Browse files
authored
Merge branch 'main' into logging
2 parents d231e87 + 508a170 commit a1e211e

1 file changed

Lines changed: 193 additions & 0 deletions

File tree

CLAUDE.md

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
Red Hat Lightspeed Agent for Google Cloud — an A2A-ready (Agent-to-Agent protocol) AI agent providing access to Red Hat Insights, built on Google Agent Development Kit (ADK), Gemini 2.5 Flash, and a Red Hat Lightspeed MCP server sidecar. Integrates with Google Cloud Marketplace for provisioning, billing, and metering.
8+
9+
## Common Commands
10+
11+
### Development
12+
13+
Always use a Python virtual environment — do not install dependencies system-wide.
14+
15+
```bash
16+
python3.12 -m venv .venv # Create virtual environment
17+
source .venv/bin/activate # Activate it
18+
pip install -e ".[agent,dev]" # Install all dependencies (agent + dev)
19+
# Optional: pip install -e ".[agent,dev,telemetry]" # Include Jaeger/Zipkin exporters
20+
python -m lightspeed_agent.main # Run the agent API server (port 8000)
21+
```
22+
23+
### Testing
24+
25+
Ensure the virtual environment is activated before running tests.
26+
27+
```bash
28+
make test # Run all tests
29+
python -m pytest tests/ -v # Equivalent direct command
30+
python -m pytest tests/test_auth.py -v # Run a single test file
31+
python -m pytest tests/test_auth.py::test_function_name -v # Run a single test
32+
```
33+
34+
Tests use in-memory SQLite and `SKIP_JWT_VALIDATION=true` (set automatically in `tests/conftest.py`). The test suite is async — `asyncio_mode = "auto"` is configured in pyproject.toml.
35+
36+
To run with coverage:
37+
```bash
38+
python -m pytest tests/ -v --cov=src/lightspeed_agent --cov-report=term-missing
39+
```
40+
41+
### Linting & Type Checking
42+
```bash
43+
make lint # Run both ruff and mypy
44+
ruff check src/ tests/ # Linter only
45+
mypy src/lightspeed_agent/ --ignore-missing-imports # Type checker only
46+
```
47+
48+
Ruff rules: `E, F, I, N, W, UP, B, C4, SIM`. Line length: 100. Target: Python 3.12.
49+
50+
### Container Build & Operations (Podman)
51+
```bash
52+
make help # List all available targets
53+
make build # Build both images (agent + marketplace handler)
54+
make build-agent # Build agent image only
55+
make build-marketplace # Build marketplace handler image only
56+
make run # Start all pods
57+
make stop # Stop and remove pods
58+
make logs # Agent logs
59+
make logs-mcp # MCP server logs
60+
make logs-all # All container logs
61+
make status # Show pod/container status
62+
make clean # Remove containers, images, and volumes
63+
make clean-all # Full cleanup including volumes
64+
make dev # Run agent locally without containers
65+
make check-env # Validate required env vars
66+
make cve-scan # Scan for CVEs with Trivy
67+
```
68+
69+
### Before Pushing
70+
71+
Always run lint and tests before pushing commits:
72+
73+
```bash
74+
make lint && make test
75+
```
76+
77+
CI blocks merge on lint/test failures — catching issues locally saves round-trip time.
78+
79+
## Architecture
80+
81+
### Two-Service Design
82+
83+
The system runs as two separate FastAPI services with separate concerns:
84+
85+
1. **Lightspeed Agent** (port 8000, `src/lightspeed_agent/main.py`) — The AI agent service. Scales to zero on Cloud Run. Handles A2A protocol requests (JSON-RPC 2.0 at `/`), serves the AgentCard at `/.well-known/agent.json`. Uses ADK `LlmAgent` with MCP tools loaded from the sidecar.
86+
87+
2. **Marketplace Handler** (port 8001, `src/lightspeed_agent/marketplace/app.py`) — Always-on service for Google Cloud Marketplace Pub/Sub provisioning events and Dynamic Client Registration (DCR). Has a single hybrid `/dcr` endpoint that routes Pub/Sub messages vs DCR requests based on request content.
88+
89+
### Database Isolation
90+
91+
Two separate PostgreSQL databases (security boundary):
92+
- **Marketplace DB** (`DATABASE_URL`) — accounts, entitlements, DCR clients, usage records. Shared by both services.
93+
- **Session DB** (`SESSION_DATABASE_URL`) — ADK conversation sessions. Agent-only.
94+
95+
Both fall back to SQLite for development. ORM models are in `src/lightspeed_agent/db/models.py`.
96+
97+
### Authentication Flow
98+
99+
JWT tokens from Red Hat SSO flow through three layers:
100+
1. `auth/middleware.py` validates Bearer tokens on POST `/` (skips health endpoints, OpenAPI docs, agent card paths, and `/marketplace/` prefixed routes)
101+
2. Token is stored in `contextvars` for the request lifecycle
102+
3. `tools/mcp_headers.py` forwards the caller's JWT to the MCP server so it can authenticate with console.redhat.com on the user's behalf
103+
104+
Setting `SKIP_JWT_VALIDATION=true` bypasses auth (dev only, blocked when running on Cloud Run).
105+
106+
### MCP Integration
107+
108+
The agent loads tools from a Red Hat Lightspeed MCP server running as a sidecar:
109+
- Transport modes: `stdio` (dev), `http` (prod), `sse` (streaming) — configured via `MCP_TRANSPORT_MODE`
110+
- Read-only mode (`MCP_READ_ONLY=true`) filters to a safe subset of tools
111+
- Tool categories: Advisor, Inventory, Vulnerability, Remediations, Planning, Image Builder, Subscription Management, Content Sources
112+
- MCP toolset creation is in `tools/insights_tools.py`; config in `tools/mcp_config.py`
113+
114+
### Key Middleware Stack (bottom to top)
115+
1. CORS
116+
2. JWT authentication (`auth/middleware.py`)
117+
3. Redis rate limiting (`ratelimit/middleware.py`) — 60 req/min, 1000 req/hour
118+
119+
### DCR (Dynamic Client Registration)
120+
121+
Two modes controlled by `DCR_ENABLED`:
122+
- **Real DCR** (`true`): Creates OAuth clients in Red Hat SSO (Keycloak) via `dcr/keycloak_client.py`
123+
- **Static credentials** (`false`): Accepts pre-seeded client_id/secret in DCR request body
124+
125+
Client secrets are Fernet-encrypted at rest (`DCR_ENCRYPTION_KEY`).
126+
127+
### Usage Metering
128+
129+
`api/a2a/usage_plugin.py` hooks into ADK to track tokens/requests per LLM call. Hourly aggregates are stored in `UsageRecordModel` and async-reported to Google Cloud Service Control (`service_control/reporter.py`). Includes backfill for offline periods.
130+
131+
## Code Layout
132+
133+
```
134+
src/lightspeed_agent/
135+
├── api/app.py # FastAPI app factory (lifespan, middleware, routes)
136+
├── api/a2a/ # A2A protocol: routes, AgentCard, usage tracking
137+
├── auth/ # JWT validation middleware + token introspection
138+
├── config/ # Pydantic BaseSettings (all env vars, validation)
139+
├── core/agent.py # LlmAgent creation with MCP tools
140+
├── db/ # SQLAlchemy ORM (4 models, async engine)
141+
├── dcr/ # Dynamic Client Registration service
142+
├── marketplace/ # Marketplace handler (separate service entry point)
143+
├── metering/ # Usage record repository + backfill
144+
├── ratelimit/ # Redis-backed distributed rate limiter
145+
├── service_control/ # Google Cloud Service Control metering
146+
├── telemetry/ # OpenTelemetry setup (OTLP, Jaeger, Zipkin)
147+
├── tools/ # MCP toolset definitions + JWT header forwarding
148+
└── main.py # Agent service entry point
149+
```
150+
151+
## Configuration
152+
153+
All configuration is via environment variables, managed through Pydantic settings in `config/settings.py`. See `.env.example` for the complete list (30+ vars). Key variables:
154+
155+
**LLM / Google Cloud:**
156+
- `GOOGLE_API_KEY` or `GOOGLE_CLOUD_PROJECT` + `GOOGLE_GENAI_USE_VERTEXAI=TRUE` (LLM access)
157+
- `GEMINI_MODEL` (model selection, default: `gemini-2.5-flash`)
158+
159+
**Database:**
160+
- `DATABASE_URL` / `SESSION_DATABASE_URL` (PostgreSQL or SQLite)
161+
162+
**Auth:**
163+
- `RED_HAT_SSO_CLIENT_ID` / `RED_HAT_SSO_CLIENT_SECRET`
164+
- `SKIP_JWT_VALIDATION` (dev only)
165+
166+
**MCP:**
167+
- `MCP_TRANSPORT_MODE`, `MCP_SERVER_URL`
168+
169+
**DCR:**
170+
- `DCR_ENABLED`, `DCR_ENCRYPTION_KEY`
171+
172+
**Agent:**
173+
- `AGENT_HOST`, `AGENT_PORT`
174+
175+
**Service Control:**
176+
- `SERVICE_CONTROL_SERVICE_NAME`, `SERVICE_CONTROL_ENABLED`
177+
178+
**Rate Limiting:**
179+
- `RATE_LIMIT_REDIS_URL`
180+
181+
**Observability:**
182+
- `LOG_LEVEL`, `LOG_FORMAT`
183+
- `OTEL_ENABLED`, `OTEL_EXPORTER_TYPE`, `OTEL_SERVICE_NAME`
184+
185+
## CI Pipeline
186+
187+
GitHub Actions (`.github/workflows/ci.yml`) runs on CentOS Stream 9 with Python 3.12:
188+
1. **Lint** — ruff + mypy
189+
2. **Test** — pytest
190+
3. **Build** — Podman container build
191+
4. **CI Gate** — blocks merge if any job fails
192+
193+
Secret scanning is configured via `.gitleaks.toml`.

0 commit comments

Comments
 (0)