feat(types): add core type system and Zod schemas#6
Conversation
Add schemas/ with Zod-first type definitions for the seven ST-007 domains plus rate limiting: providers (LLMProvider, ModelInfo, ProviderConfig), messages (ChatMessage, StreamChunk, APIError), storage (UserSettings, APIKeyStore, WidgetPosition, RateLimitState), macros (PromptMacro, MacroLibrary), context detection (PageContext, ContextOverride), PII detection (PIITier, PIIPattern, PIIMatch), and telemetry (TelemetryEvent, TelemetryPayload). Every type is derived via z.infer from its Zod schema, keeping validation and typing as a single source of truth for later storage, message-passing, and API response validation. Restrict TelemetryEvent.metadata values to primitives (string, number, boolean) instead of z.unknown(), as defense-in-depth against structured PII or large payloads riding along in a telemetry event. Add .env/.env.* to .gitignore (with a .env.example allowlist) ahead of API key handling work. This is foundational groundwork only - no entrypoint consumes these schemas yet; usage lands starting with ST-008 (storage) and ST-010 (provider factory). Refs: ST-007
📝 WalkthroughWalkthroughThis PR adds Zod-based schemas and inferred types for chat, context, macros, PII, providers, storage, and telemetry, re-exports them from a schema barrel, and updates ChangesSchema Definitions
Estimated code review effort: 2 (Simple) | ~12 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
schemas/pii.tsESLint skipped: missing config or dependency (missing-dependency). The ESLint configuration references a package that is not available in the sandbox. schemas/storage.tsESLint skipped: the ESLint configuration for this file references a package that is not available in the sandbox. schemas/telemetry.tsESLint skipped: the ESLint configuration for this file references a package that is not available in the sandbox. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@schemas/pii.ts`:
- Around line 14-22: The PIIMatchSchema currently accepts any numeric startIndex
and endIndex, so malformed matches can slip through and break masking logic. Add
validation to PIIMatchSchema to enforce non-negative indices and require
endIndex to be greater than startIndex, using a schema-level refinement on the
PIIMatchSchema object. Keep the constraint close to the existing
PIIMatchSchema/PIIMatch type definitions so invalid PIIMatch values are rejected
before substring slicing occurs.
In `@schemas/storage.ts`:
- Around line 29-44: APIKeyStoreSchema currently hardcodes provider keys, which
duplicates the provider list and can drift from the enum. Update the schema in
schemas/storage.ts to derive its object shape from LLMProviderSchema using
z.partialRecord(LLMProviderSchema, z.string().min(1)), and keep the existing “at
least one API key is required” refine. Make sure APIKeyStore continues to infer
from the updated schema so all provider keys stay in sync automatically.
In `@schemas/telemetry.ts`:
- Line 22: The anonymousUuid schema is too permissive because it currently uses
z.string(), so update the telemetry schema to validate it as a real UUID using
Zod’s uuid validator. Make the change in the telemetry schema definition where
anonymousUuid is declared so the field name and validation rule match, and keep
the rest of the schema unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: f328c10f-393c-4baa-a9ac-5c4d0fe838b7
📒 Files selected for processing (9)
.gitignoreschemas/chat.tsschemas/context.tsschemas/index.tsschemas/macro.tsschemas/pii.tsschemas/provider.tsschemas/storage.tsschemas/telemetry.ts
Add ordering/bounds validation to PIIMatchSchema (non-negative integer indices, endIndex strictly greater than startIndex) to prevent a malformed match from later causing invalid substring slicing during PII masking. Derive APIKeyStoreSchema from LLMProviderSchema via z.partialRecord instead of hand-duplicating the four provider names, which as a side effect now rejects unknown/misspelled provider keys instead of silently stripping them. Validate TelemetryEvent.anonymousUuid as an actual UUID (z.uuid()) instead of an unconstrained string, matching its documented purpose. Refs: ST-007
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
schemas/storage.ts (1)
42-48: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winTighten numeric constraints on
RateLimitStateSchema.
requestCount,windowStart, andnextAvailableAtare plainz.number(), allowing negative or fractional values that don't make sense for a request counter or epoch timestamp.♻️ Suggested tightening
export const RateLimitStateSchema = z.object({ provider: LLMProviderSchema, - requestCount: z.number(), - windowStart: z.number(), - nextAvailableAt: z.number(), + requestCount: z.number().int().nonnegative(), + windowStart: z.number().int().nonnegative(), + nextAvailableAt: z.number().int().nonnegative(), });🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@schemas/storage.ts` around lines 42 - 48, Tighten the numeric validation in RateLimitStateSchema so requestCount, windowStart, and nextAvailableAt only accept sensible non-negative whole-number values instead of any number. Update the RateLimitStateSchema definition in schemas/storage.ts to use stricter constraints for these fields, and keep the existing RateLimitState type inference unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@schemas/storage.ts`:
- Around line 42-48: Tighten the numeric validation in RateLimitStateSchema so
requestCount, windowStart, and nextAvailableAt only accept sensible non-negative
whole-number values instead of any number. Update the RateLimitStateSchema
definition in schemas/storage.ts to use stricter constraints for these fields,
and keep the existing RateLimitState type inference unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: dd203446-6d49-4490-832a-8310dc0ac556
📒 Files selected for processing (3)
schemas/pii.tsschemas/storage.tsschemas/telemetry.ts
Summary
schemas/with Zod-first type definitions across 8 domains: providers (LLMProvider,ModelInfo,ProviderConfig), chat (ChatMessage,StreamChunk,APIError), storage (UserSettings,APIKeyStore,WidgetPosition,RateLimitState), macros (PromptMacro,MacroLibrary), context detection (PageContext,ContextOverride), PII detection (PIITier,PIIPattern,PIIMatch), and telemetry (TelemetryEvent,TelemetryPayload).RateLimitStatewas added beyond the original ST-007 scope by explicit request — it's documented in the technical-decisions doc alongside providers/APIError and will be needed by ST-031.z.infer<typeof XSchema>— Zod schemas are the single source of truth for both runtime validation and TypeScript types, ready for storage validation (ST-008), message-passing between content script/background/popup, and API response validation (ST-010/011).TelemetryEvent.metadatato primitive values (string | number | boolean) instead ofz.unknown(), as defense-in-depth against structured PII or large payloads riding along in a telemetry event..env/.env.*to.gitignore(with a.env.exampleallowlist) ahead of upcoming API key handling work.Notes for reviewers
entrypoints/file imports any of these schemas yet. Actual usage lands starting with ST-008 (storage layer) and ST-010 (provider factory).APIKeyStore's.refine():Object.values()on an object with optional properties can silently dropundefinedfrom the inferred element type, which made@typescript-eslint/no-unnecessary-conditionflag a legitimate null-check as dead code. Fixed by checking each field directly instead of iterating.Test plan
pnpm run compile— no type errorspnpm run lint— zero errorspnpm run format:check— all files match Prettier stylepnpm run build— MV3 output builds correctly, bundle size unchanged (nothing consumes these schemas yet)LLMProviderSchema,APIKeyStoreSchema,WidgetPositionSchema, andUserSettingsSchemaaccept valid input and reject invalid input as expectedRefs: ST-007
Summary by CodeRabbit
.envand.env.*by default, while keeping.env.exampletracked.