[AgentOps][Code Quality] Better organization for env [1/n]#443
[AgentOps][Code Quality] Better organization for env [1/n]#443XinweiHe merged 1 commit intopivot/agentopsfrom
Conversation
Greptile OverviewGreptile SummaryThis PR centralizes environment variable access across the Python backend and Next.js frontend.
Main integration point is the shared-secret flow between backend and Next.js internal API routes: the backend now sources Confidence Score: 3/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant Env as Env/.env
participant Rest as FastAPI (backend/rest)
participant Settings as backend/shared/config.settings
participant UI as Next.js (frontend/ui)
participant Zod as frontend/ui/src/env.ts
participant Public as REST /public/traces
participant Deps as REST auth deps
participant Celery as Celery worker
Rest->>Env: load_dotenv()
Rest->>Settings: import settings (Pydantic Settings)
UI->>Zod: parse(process.env)
Public->>Settings: read traceroot_ui_url, internal_api_secret
Public->>UI: POST /api/internal/validate-api-key (X-Internal-Secret)
Deps->>Settings: read traceroot_ui_url, internal_api_secret
Deps->>UI: POST /api/internal/validate-project-access (X-Internal-Secret)
Public->>Celery: process_s3_traces.delay(s3_key, project_id)
|
|
@greptile review |
| # Internal communication (Python <-> Next.js) | ||
| traceroot_ui_url: str = "http://localhost:3000" | ||
| internal_api_secret: str = "" | ||
|
|
There was a problem hiding this comment.
Empty internal secret
internal_api_secret defaults to "", which means the backend can start up without INTERNAL_API_SECRET and then all internal auth calls that send X-Internal-Secret will fail at runtime (or, if the frontend is also configured with an empty secret, effectively disables the shared-secret check). If the intent is “fail fast at startup”, this should be validated as non-empty (no default) so misconfiguration is caught immediately.
| const serverSchema = z.object({ | ||
| NEXTAUTH_SECRET: z.string().min(1), | ||
| NEXTAUTH_URL: z.string().default("http://localhost:3000"), | ||
| INTERNAL_API_SECRET: z.string(), | ||
| AUTH_GOOGLE_CLIENT_ID: z.string().default(""), |
There was a problem hiding this comment.
Secret can be empty
INTERNAL_API_SECRET is validated with z.string() (no .min(1)), so an explicitly-set empty string will pass schema validation and verifyInternalSecret() will treat an empty X-Internal-Secret as valid. This makes it easy to accidentally disable internal API authentication; this value should be validated as non-empty.
Summary
os.getenv()/process.env.*reads with hardcoded defaults duplicated at each call siteType of Change
Details
Backend (Python)
New
backend/shared/config.pyusing Pydantic Settings:Settingsclass validates all env vars (CLICKHOUSE_*,S3_*,REDIS_URL,INTERNAL_API_SECRET, etc.)rest,worker,db/clickhouse) now import frombackend.shared.configinstead of readingos.getenv()directlyAlso cleans up
backend/worker/structure:tasks.py→ingest_tasks.py,transformer.py→otel_transform.py(clearer naming)features/tokens/→tokens/__init__.pyfiles and stale test fileFrontend (TypeScript)
Two new Zod schema files following the server/client split required by Next.js:
frontend/ui/src/env.ts— server-only vars (NEXTAUTH_SECRET,INTERNAL_API_SECRET, SMTP config, Google OAuth)frontend/ui/src/env.client.ts— client-safeNEXT_PUBLIC_*vars with explicitprocess.envreferences for Next.js static replacementUpdated 6 files to import from the centralized schemas instead of reading
process.env.*directly.Screenshots / Recordings (if applicable)
N/A — no UI changes, purely internal refactor.
Checklist