feat(core): add experimental Valibot schema validation#160
feat(core): add experimental Valibot schema validation#160halvaradop merged 3 commits intomasterfrom
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
|
Warning Rate limit exceeded
To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
📝 WalkthroughWalkthroughAdds experimental Valibot schema support and generalizes identity/type utilities from Zod-only to a unified Identities/FromShapeToObject model; updates runtime schema handling, type declarations, tests, and adds ChangesValibot + Identity Generalization
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: Turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. 👉 Get your free trial and get 200 agent minutes per Slack user (a $50 value). 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. Review rate limit: 0/1 reviews remaining, refill in 43 minutes and 21 seconds.Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (2)
packages/core/test/types.test-d.ts (1)
19-37: ⚡ Quick winAdd a concrete Valibot case instead of only asserting through
Shapes.These assertions can still pass through the default Zod path, so they don't actually prove that
createAuth({ identity: { schema: ... } })resolves the Valibot branch correctly. A dedicatedUserIdentityValibotinstantiation here would give the experimental feature real type coverage instead of relying on a union alias.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/core/test/types.test-d.ts` around lines 19 - 37, Add a dedicated Valibot test case instead of only using the union alias Shapes: create a concrete Valibot identity (e.g., a UserIdentityValibot type or inline identity object with a Valibot schema) and call createAuth({ identity: { schema: /* valibot schema */ } }) (or createAuth({ oauth: [], identity: ... })) then add expectTypeOf assertions for the resulting instance methods (api.getSession, api.updateSession, jose.signJWS, jose.verifyJWS) to ensure they resolve to the Valibot-mapped types (reference ValibotShapeToObject, UserShapeValibot, AuthConfig, and FromShapeToObject/Identities) so the Valibot branch is covered explicitly.packages/core/src/@types/utility.ts (1)
5-5: ⚡ Quick winUse type-only import for
UserShapeValibot.
UserShapeValibotis only used as a type constraint in line 33. In a types-only file, preferimport typefor consistency with line 4 and to avoid pulling in runtime code unnecessarily.♻️ Proposed fix
-import { UserShapeValibot } from "@/shared/identity.ts" +import type { UserShapeValibot } from "@/shared/identity.ts"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/core/src/`@types/utility.ts at line 5, The import for UserShapeValibot is only used as a type, so change the runtime import to a type-only import: replace the current import of UserShapeValibot with an "import type" declaration to match the existing type-only imports (see the import at top of the file) and satisfy the type constraint usage of UserShapeValibot in the utility type around the code that references it (the type usage on/near line 33).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/core/src/actions/updateSession/updateSession.ts`:
- Around line 27-28: In updateSession (the code building the session payload
where you already changed ctx.body?.user), also null-guard the expires access:
replace ctx.body.expires with an optional-chained access and protect the
toISOString call (e.g., use ctx.body?.expires?.toISOString()) so that when
ctx.body is undefined you won't attempt to read expires or call toISOString;
update the session construction that references ctx.body.expires accordingly.
In `@packages/core/src/createAuth.ts`:
- Around line 79-80: The createAuth generic currently lacks a default which
widens calls like createAuth({ oauth: [] }) to the whole Identities union;
change the signature of createAuth<Identity extends Identities> to provide the
built-in Zod identity as the default (e.g. createAuth<Identity extends
Identities = BuiltInZodIdentity>) so that when callers omit the generic they get
the Zod-based identity shape; keep the rest of the implementation (creating
authInstance via createAuthInstance<Identity>(config) and the
AuthInstance<FromShapeToObject<Identity>> cast) the same, and apply the same
default pattern wherever createAuth is meant to be directly callable with the
built-in identity.
In `@packages/core/src/shared/identity.ts`:
- Around line 34-39: The createIdentity function's Valibot branch never matches
because raw Valibot entries don't carry Symbol.for("valibot"), so the code
always falls through to return z.object(shape); fix by detecting Valibot entries
and returning a Valibot schema: inside createIdentity (and when handling
UserShapeValibot) check for the Valibot structure (e.g., shape is an object of
entries or lacks the valibot symbol) and wrap those raw entries with
valibot.object(shape) before returning; keep the existing Symbol.for("valibot")
path for already-constructed Valibot schemas and retain z.object(shape) only for
Zod shapes.
---
Nitpick comments:
In `@packages/core/src/`@types/utility.ts:
- Line 5: The import for UserShapeValibot is only used as a type, so change the
runtime import to a type-only import: replace the current import of
UserShapeValibot with an "import type" declaration to match the existing
type-only imports (see the import at top of the file) and satisfy the type
constraint usage of UserShapeValibot in the utility type around the code that
references it (the type usage on/near line 33).
In `@packages/core/test/types.test-d.ts`:
- Around line 19-37: Add a dedicated Valibot test case instead of only using the
union alias Shapes: create a concrete Valibot identity (e.g., a
UserIdentityValibot type or inline identity object with a Valibot schema) and
call createAuth({ identity: { schema: /* valibot schema */ } }) (or createAuth({
oauth: [], identity: ... })) then add expectTypeOf assertions for the resulting
instance methods (api.getSession, api.updateSession, jose.signJWS,
jose.verifyJWS) to ensure they resolve to the Valibot-mapped types (reference
ValibotShapeToObject, UserShapeValibot, AuthConfig, and
FromShapeToObject/Identities) so the Valibot branch is covered explicitly.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: e3583353-7e79-486a-8dd1-5bd97041d499
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (11)
packages/core/package.jsonpackages/core/src/@types/config.tspackages/core/src/@types/session.tspackages/core/src/@types/utility.tspackages/core/src/actions/updateSession/updateSession.tspackages/core/src/createAuth.tspackages/core/src/router/context.tspackages/core/src/session/strategy.tspackages/core/src/shared/identity.tspackages/core/src/shared/logger.tspackages/core/test/types.test-d.ts
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/core/src/@types/config.ts (1)
349-353:⚠️ Potential issue | 🟠 Major | ⚡ Quick win
RouterGlobalContext.identity.schemais still Zod-only.The
IdentityConfigtype (line 287) was updated to acceptZodObject<any> | ObjectSchema<any, undefined>, butRouterGlobalContext.identity.schemaon line 351 remains hardcoded toZodObject<any>. This creates a type inconsistency when Valibot schemas are used at runtime.🐛 Proposed fix
identity: { unknownKeys: "passthrough" | "strict" | "strip" - schema: ZodObject<any> + schema: ZodObject<any> | ObjectSchema<any, undefined> skipValidation?: boolean }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/core/src/`@types/config.ts around lines 349 - 353, Update the RouterGlobalContext.identity.schema type to match IdentityConfig by allowing both Zod and Valibot schemas: change the hardcoded ZodObject<any> to the union type used in IdentityConfig (e.g., ZodObject<any> | ObjectSchema<any, undefined>) so RouterGlobalContext.identity.schema and IdentityConfig share the same schema type; ensure you reference the same union type wherever RouterGlobalContext.identity.schema is declared to eliminate the type mismatch.
🧹 Nitpick comments (2)
packages/core/src/schema-registry.ts (1)
50-56: ⚡ Quick winValibot validation errors lose detail information.
When Valibot validation fails,
detailsis an empty object{}(line 51), andcauseisundefined(line 53). This discards useful error information that could help developers debug validation failures. Valibot provides error formatting utilities likeflattenthat could be used similarly toformatZodError.♻️ Proposed fix to include Valibot error details
+import { flatten } from "valibot" + +const formatValibotError = (error: any) => { + return flatten(error.issues) +} + const parse = async (data: unknown = {}) => { const isZod = isZodSchema(schema) const parsed: any = isZod ? await schema.safeParseAsync(data) : await safeParseAsync(schema as any, data) if (!parsed.success) { - const details = JSON.stringify(isZod ? formatZodError(parsed.error) : {}, null, 2) + const details = JSON.stringify(isZod ? formatZodError(parsed.error) : formatValibotError(parsed), null, 2) throw new AuthValidationError("INVALID_IDENTITY_VALIDATION_FAILED", details, { - cause: isZod ? parsed.error : undefined, + cause: isZod ? parsed.error : parsed.issues, }) } return isZod ? parsed.data : parsed.output }Apply the same pattern to
parseAsPartial(lines 59-69).🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/core/src/schema-registry.ts` around lines 50 - 56, The Valibot branch currently discards useful error info: when parsed.success is false and isZod is false the code builds details as an empty object and sets cause undefined; update the error handling in the parsed failure branch (and mirror the same change in parseAsPartial) to include Valibot's formatted errors (e.g., use valibot.flatten or equivalent flattening/formatting util) so details contains the readable error structure and pass the original parsed.error as the cause to AuthValidationError; keep the existing Zod handling (formatZodError and cause) for isZod true and apply the Valibot formatting when isZod is false so both details and cause carry useful info.packages/core/test/identity.test.ts (1)
128-138: 💤 Low valueMisleading test data comment in passthrough tests.
The
extraKeyvalue is"should be stripped"(line 113), but in passthrough mode tests (lines 128-138, 160-170), this key is intentionally preserved. The comment is misleading given the test context.✏️ Suggested improvement
Consider updating the test payload or using a more neutral value:
const payload = { sub: "user123", name: "John Doe", role: "admin", - extraKey: "should be stripped", + extraKey: "extra value", }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/core/test/identity.test.ts` around lines 128 - 138, The test data uses payload.extraKey = "should be stripped" which is misleading for the passthrough-mode tests; update the test payload or its comment so the value reflects that passthrough preserves unknown keys (e.g., change the string to "preserved in passthrough" or a neutral value) and ensure assertions in the "zod schema with 'passthrough' unknownKeys" test that calls stripUnknownKeys(zodSchema, "passthrough") remain accurate; locate the payload variable and the test by the identifiers payload, zodSchema, and the test name to make the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/core/src/shared/assert.ts`:
- Around line 193-195: The runtime check in isZodSchema currently only tests for
"_def" which matches any Zod type, but the function claims to return "value is
ZodObject"; either make the runtime check actually detect an object schema
(e.g., check typeof value === "object" && value !== null && "_def" in value &&
(value as any)._def?.typeName === "ZodObject") and keep the return type
ZodObject, or change the return type to ZodTypeAny to reflect the existing broad
"_def" check; update the function signature and the runtime guard accordingly so
the type predicate and runtime behavior align (references: isZodSchema,
ZodObject, ZodTypeAny, "_def", _def.typeName).
In `@packages/core/src/shared/identity.ts`:
- Line 1: Replace the incorrect Zod destructured imports with the canonical z
import and update schema usages: remove imports of email, string, and ZodObject
and import only z (import { z } from "zod"), then update the UserIdentity schema
to call z.string() and z.email() instead of string() and email(), and update any
type references that expected ZodObject to use the z.ZodObject type or infer
with z.infer as appropriate.
---
Outside diff comments:
In `@packages/core/src/`@types/config.ts:
- Around line 349-353: Update the RouterGlobalContext.identity.schema type to
match IdentityConfig by allowing both Zod and Valibot schemas: change the
hardcoded ZodObject<any> to the union type used in IdentityConfig (e.g.,
ZodObject<any> | ObjectSchema<any, undefined>) so
RouterGlobalContext.identity.schema and IdentityConfig share the same schema
type; ensure you reference the same union type wherever
RouterGlobalContext.identity.schema is declared to eliminate the type mismatch.
---
Nitpick comments:
In `@packages/core/src/schema-registry.ts`:
- Around line 50-56: The Valibot branch currently discards useful error info:
when parsed.success is false and isZod is false the code builds details as an
empty object and sets cause undefined; update the error handling in the parsed
failure branch (and mirror the same change in parseAsPartial) to include
Valibot's formatted errors (e.g., use valibot.flatten or equivalent
flattening/formatting util) so details contains the readable error structure and
pass the original parsed.error as the cause to AuthValidationError; keep the
existing Zod handling (formatZodError and cause) for isZod true and apply the
Valibot formatting when isZod is false so both details and cause carry useful
info.
In `@packages/core/test/identity.test.ts`:
- Around line 128-138: The test data uses payload.extraKey = "should be
stripped" which is misleading for the passthrough-mode tests; update the test
payload or its comment so the value reflects that passthrough preserves unknown
keys (e.g., change the string to "preserved in passthrough" or a neutral value)
and ensure assertions in the "zod schema with 'passthrough' unknownKeys" test
that calls stripUnknownKeys(zodSchema, "passthrough") remain accurate; locate
the payload variable and the test by the identifiers payload, zodSchema, and the
test name to make the change.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: 015287c0-d4ff-4671-9b53-b5f26d6dd313
📒 Files selected for processing (9)
packages/core/CHANGELOG.mdpackages/core/src/@types/config.tspackages/core/src/actions/updateSession/updateSession.tspackages/core/src/createAuth.tspackages/core/src/schema-registry.tspackages/core/src/shared/assert.tspackages/core/src/shared/identity.tspackages/core/test/identity.test.tspackages/core/test/types.test-d.ts
✅ Files skipped from review due to trivial changes (1)
- packages/core/CHANGELOG.md
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/core/src/createAuth.ts
Description
This pull request introduces experimental support for Valibot schemas alongside Zod for defining and validating user identities in Aura Auth.
Valibot schemas can now be used through the
identity.schemaconfiguration to validate identity data across internal authentication flows, including default fields such as:subnameemailimageas well as any additional custom fields defined by the consumer.
Aura Auth internally validates and verifies identity payloads during authentication and session flows.
With this update, the
identity.schemaoption now supports:This validation layer is used to ensure the integrity and consistency of user identity data throughout the authentication lifecycle.
Experimental Status
Warning
Valibot support is currently experimental and may introduce unexpected behavior or incomplete type inference in some flows.
At the moment, the internal router used by Aura Auth does not fully support Valibot schema inference across all endpoints.
Known limitation:
POST /auth/sessionmay not infer the complete schema correctly when using ValibotOther authentication endpoints are fully supported.
This limitation will be addressed as router-level Valibot support continues to evolve.
Changes
createAuthto accept Valibot-based identity definitionsusage