Skip to content

Feature/proto driven sdk - #38

Merged
SteakFisher merged 4 commits into
mainfrom
feature/role-based-apikeys
May 14, 2026
Merged

Feature/proto driven sdk#38
SteakFisher merged 4 commits into
mainfrom
feature/role-based-apikeys

Conversation

@thedevyashsaini

@thedevyashsaini thedevyashsaini commented May 14, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • Refactor
    • Updated internal data validation mappings to use protobuf enum values instead of hardcoded numeric indices for improved maintainability.

Review Change Stack

Proto CreateAPIKeyRequest lacks a role field. Read role from the gRPC
metadata header x-scrawn-role instead. Zod schema defaults to production
if not specified. Only dashboard callers can create keys.
- SdkCallField, AiTokenField, PaymentField enums in query.proto
- Per-table enums (UsersField, SessionsField, etc.) in data.proto
- Regenerated proto stubs include new enum types
…proto enums

- query.ts + data.ts: OPERATOR_MAP, LOGICAL_MAP, AGGREGATION_TYPE_MAP
  now use proto Operator/LogicalOperator/AggregationType enum values
- Remove hardcoded number literals — single source of truth is proto
@coderabbitai

coderabbitai Bot commented May 14, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

The PR updates Zod schema validation modules in src/zod/ to derive numeric-to-string operator, logical, and aggregation-type mappings from protobuf enum constants instead of hardcoded numeric keys. Both data.ts and query.ts add protobuf enum imports and rekey their internal lookup tables to use enum values, preserving exported schema shapes while aligning transformation logic with generated protobuf definitions.

Changes

Operator and Logical Type Enum Mappings

Layer / File(s) Summary
Data query schema operator and logical enum mapping
src/zod/data.ts
Operator and LogicalOperator protobuf enums are imported, and OPERATOR_MAP and LOGICAL_MAP are rekeyed to use enum constants instead of fixed numeric indices for Zod schema field transformation.
Query validation schema operator, aggregation, and logical enum mapping
src/zod/query.ts
Operator, AggregationType, and LogicalOperator protobuf enums are imported, and all three mapping tables (OPERATOR_MAP, AGGREGATION_TYPE_MAP, LOGICAL_MAP) are rekeyed to use enum constants, aligning query schema transformations with protobuf enum definitions.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • ScrawnDotDev/Scrawn#36: The PR's changes to operator and logical enum mappings in Zod schemas directly support how the new queryData gRPC handler consumes and validates where.operator and where.logical fields.

Poem

🐰 Enums now dance where numbers used to play,
Protobuf keys light the mapping way,
Data and query schemas aligned,
Transformation tables redesigned!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'Feature/proto driven sdk' is vague and generic, failing to clearly describe the specific changes made to the codebase. Use a more descriptive title that specifically indicates the primary change, such as 'Use protobuf enum values in Zod schema mappings' or 'Update operator and logical operator mappings to use protobuf enums'.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/role-based-apikeys

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

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
src/zod/query.ts (1)

5-22: ⚡ Quick win

Make enum validation key-driven across operator/logical/aggregation.

These maps are proto-keyed now, but schema checks still use fixed numeric bounds. That leaves room for map/validator drift and transform-to-undefined behavior when enum values evolve.

Proposed refactor
 const OPERATOR_MAP = {
   [Operator.EQ]: "EQ",
   [Operator.GT]: "GT",
   [Operator.GTE]: "GTE",
   [Operator.LT]: "LT",
   [Operator.LTE]: "LTE",
   [Operator.NEQ]: "NEQ",
 } as const;
@@
 const AGGREGATION_TYPE_MAP = {
   [AggregationType.SUM]: "SUM",
   [AggregationType.COUNT]: "COUNT",
 } as const;
@@
 const LOGICAL_MAP = {
   [LogicalOperator.AND]: "AND",
   [LogicalOperator.OR]: "OR",
 } as const;
+
+const OPERATOR_CODES = new Set<number>(Object.keys(OPERATOR_MAP).map(Number));
+const AGGREGATION_CODES = new Set<number>(Object.keys(AGGREGATION_TYPE_MAP).map(Number));
+const LOGICAL_CODES = new Set<number>(Object.keys(LOGICAL_MAP).map(Number));
@@
   operator: z
     .number()
     .int()
-    .min(1)
-    .max(6)
-    .transform((v) => OPERATOR_MAP[v as keyof typeof OPERATOR_MAP]),
+    .refine((v): v is keyof typeof OPERATOR_MAP => OPERATOR_CODES.has(v), {
+      error: "Invalid operator",
+    })
+    .transform((v) => OPERATOR_MAP[v]),
@@
       logical: z
         .number()
         .int()
-        .min(0)
-        .max(2)
-        .transform(
-          (v) => LOGICAL_MAP[v as keyof typeof LOGICAL_MAP]
-        ),
+        .refine((v): v is keyof typeof LOGICAL_MAP => LOGICAL_CODES.has(v), {
+          error: "Invalid logical operator",
+        })
+        .transform((v) => LOGICAL_MAP[v]),
@@
   type: z
     .number()
     .int()
-    .min(1)
-    .max(2)
-    .transform(
-      (v) => AGGREGATION_TYPE_MAP[v as keyof typeof AGGREGATION_TYPE_MAP]
-    ),
+    .refine(
+      (v): v is keyof typeof AGGREGATION_TYPE_MAP => AGGREGATION_CODES.has(v),
+      { error: "Invalid aggregation type" }
+    )
+    .transform((v) => AGGREGATION_TYPE_MAP[v]),
🤖 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 `@src/zod/query.ts` around lines 5 - 22, The current
operator/logical/aggregation validators use fixed numeric bounds which can drift
from the maps; instead make validation key-driven by deriving allowed keys from
OPERATOR_MAP, AGGREGATION_TYPE_MAP, and LOGICAL_MAP (e.g., use Object.keys or
keyof typeof <MAP>) and build the Zod validators/enums from those derived keys
so the schema always matches the transform maps; update any schema functions
that reference numeric bounds to use these map-derived key sets (look for
validations around Operator, AggregationType, LogicalOperator) and ensure
transforms use the same maps to avoid producing undefined.
src/zod/data.ts (1)

12-25: ⚡ Quick win

Derive accepted codes from enum-key maps, not fixed numeric ranges.

OPERATOR_MAP/LOGICAL_MAP are now proto-driven, but the validators still use hardcoded .min()/.max() bounds. That can drift from enum values and allow transforms to return undefined for unmapped codes.

Proposed refactor
 const OPERATOR_MAP = {
   [Operator.EQ]: "EQ",
   [Operator.GT]: "GT",
   [Operator.GTE]: "GTE",
   [Operator.LT]: "LT",
   [Operator.LTE]: "LTE",
   [Operator.NEQ]: "NEQ",
   [Operator.CONTAINS]: "CONTAINS",
 } as const;
 
 const LOGICAL_MAP = {
   [LogicalOperator.AND]: "AND",
   [LogicalOperator.OR]: "OR",
 } as const;
+
+const OPERATOR_CODES = new Set<number>(Object.keys(OPERATOR_MAP).map(Number));
+const LOGICAL_CODES = new Set<number>(Object.keys(LOGICAL_MAP).map(Number));
@@
   operator: z
     .number()
     .int()
-    .min(1)
-    .max(7)
-    .transform((v) => OPERATOR_MAP[v as keyof typeof OPERATOR_MAP]),
+    .refine((v): v is keyof typeof OPERATOR_MAP => OPERATOR_CODES.has(v), {
+      error: "Invalid operator",
+    })
+    .transform((v) => OPERATOR_MAP[v]),
@@
       logical: z
         .number()
         .int()
-        .min(0)
-        .max(2)
-        .transform((v) => LOGICAL_MAP[v as keyof typeof LOGICAL_MAP]),
+        .refine((v): v is keyof typeof LOGICAL_MAP => LOGICAL_CODES.has(v), {
+          error: "Invalid logical operator",
+        })
+        .transform((v) => LOGICAL_MAP[v]),
🤖 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 `@src/zod/data.ts` around lines 12 - 25, Validators that currently rely on
hardcoded .min()/.max() ranges should instead validate against the actual keys
of OPERATOR_MAP and LOGICAL_MAP so unmapped/changed enum values don't slip
through; replace the .min/.max() checks with a membership check built from the
maps (e.g., compute allowed = new Set(Object.keys(OPERATOR_MAP).map(Number)) and
use z.number().refine(v => allowed.has(v), { message: ... }) or use
z.nativeEnum(Operator)/z.nativeEnum(LogicalOperator) where appropriate) so
validation is driven from OPERATOR_MAP and LOGICAL_MAP rather than fixed numeric
ranges.
🤖 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.

Nitpick comments:
In `@src/zod/data.ts`:
- Around line 12-25: Validators that currently rely on hardcoded .min()/.max()
ranges should instead validate against the actual keys of OPERATOR_MAP and
LOGICAL_MAP so unmapped/changed enum values don't slip through; replace the
.min/.max() checks with a membership check built from the maps (e.g., compute
allowed = new Set(Object.keys(OPERATOR_MAP).map(Number)) and use
z.number().refine(v => allowed.has(v), { message: ... }) or use
z.nativeEnum(Operator)/z.nativeEnum(LogicalOperator) where appropriate) so
validation is driven from OPERATOR_MAP and LOGICAL_MAP rather than fixed numeric
ranges.

In `@src/zod/query.ts`:
- Around line 5-22: The current operator/logical/aggregation validators use
fixed numeric bounds which can drift from the maps; instead make validation
key-driven by deriving allowed keys from OPERATOR_MAP, AGGREGATION_TYPE_MAP, and
LOGICAL_MAP (e.g., use Object.keys or keyof typeof <MAP>) and build the Zod
validators/enums from those derived keys so the schema always matches the
transform maps; update any schema functions that reference numeric bounds to use
these map-derived key sets (look for validations around Operator,
AggregationType, LogicalOperator) and ensure transforms use the same maps to
avoid producing undefined.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8ceff87f-505e-4294-86c7-cba8e1ff02cc

📥 Commits

Reviewing files that changed from the base of the PR and between 036c0de and c5cff4e.

⛔ Files ignored due to path filters (4)
  • src/gen/data/v1/data_pb.d.ts is excluded by !**/gen/**
  • src/gen/data/v1/data_pb.js is excluded by !**/gen/**
  • src/gen/query/v1/query_pb.d.ts is excluded by !**/gen/**
  • src/gen/query/v1/query_pb.js is excluded by !**/gen/**
📒 Files selected for processing (2)
  • src/zod/data.ts
  • src/zod/query.ts

@SteakFisher
SteakFisher merged commit ae54731 into main May 14, 2026
2 of 3 checks passed
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