Conversation
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…iance annotations The `ClientContract` type graph was dominated by two type-checking costs on non-trivial schemas: 1. The inferred client `Options` literal (heavy `computedFields`/`procedures` function types) was threaded as a type argument into every model's `ModelOperations` (30+ instantiations). 2. TypeScript spent most of the time *measuring* variance of the large, recursive CRUD generics - measurement that comes back "unreliable" and is pure wasted work. Fixes: - Add `QueryRelevantOptions` and project `Options` to its query-relevant subset (`omit`/`slicing`) at the model-map fan-out, so the heavy literal stays out of the per-model types. - Add explicit variance annotations to `ModelOperations`, `CommonModelOperations`, `ZodSchemaFactory`, and the leaf CRUD arg/filter types so the checker skips the expensive (and unreliable) variance measurement. On the taskforge sample (34 models): ~2.78M -> ~0.95M type instantiations and ~4.4s -> ~1.6s check time (~66% / ~64%). Trade-off: `Options` is invariant on the model operations, so a client built with an explicit `omit`/`slicing` literal is no longer assignable to the bare `ClientContract<SchemaDef>` (default options). Schema-agnostic call sites that take `ClientContract<SchemaDef>` should widen via a cast; `proxy.ts` is updated accordingly. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extends the variance annotations to `ToOneRelationUpdateInput`, `FilterArgs`, `SortAndTakeArgs`, and `ZodSchemaFactory`, whose `Options` parameter was still being measured (the largest remaining variance cost). The client is already invariant in `Options`, so this introduces no new assignability constraints. Annotating `ToOneRelationUpdateInput` also short-circuits measurement of its conditional children (`DisconnectInput`/`NestedDeleteInput`), which can't carry annotations directly. taskforge sample: ~0.95M -> ~0.55M instantiations, ~1.6s -> ~1.0s check time (cumulative from baseline: ~2.78M -> ~0.55M, ~4.4s -> ~1.0s). Validated: all ORM-dependent packages typecheck clean; e2e client-api (618), omit/slicing/computed (74), and type-level (45) suites pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…e holds Making `Options` invariant on the leaf arg types (previous commit) regressed client assignability: `ZodSchemaFactory` received the *unprojected* options via `$zod`, so it produced `FilterArgs<…, fullOptions>`, and the invariant `Options` then required the heavy options literal (carrying `dialect`) to match exactly - breaking `ClientContract<S, Literal>` -> `ClientContract<S>` (e.g. the taskforge sample's `db: DB`). Fix: pass the client's *query-relevant* (projected) options to `ZodSchemaFactory` via the `$zod` accessor, relax its bound to `QueryOptions`, erase the client `Options` arg in its constructor, and read the runtime-only `plugins` field weakly. Now every path that instantiates the leaf arg types feeds them projected options, so their invariance no longer constrains the options literal. taskforge sample: 0 errors, ~0.55M instantiations, ~1.0s. All ORM-dependent packages typecheck clean; zod/omit/slicing (257) and type-level (45) suites pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…iance annotations (#2702)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…de is false (#2671) `allowQueryTimeOmitOverride: false` only guarded the query-time `omit` clause, so an omitted field could still be un-omitted (leaked) via an explicit `select: { field: true }`. The select schema now only accepts `false` for config-omitted fields when query-time override is disallowed, rejecting such selects with a validation error. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
#2709) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
#2723) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
| GitGuardian id | GitGuardian status | Secret | Commit | Filename | |
|---|---|---|---|---|---|
| 33485392 | Triggered | Generic Private Key | 4f462a7 | packages/cli/test/proxy.test.ts | View secret |
🛠 Guidelines to remediate hardcoded secrets
- Understand the implications of revoking this secret by investigating where it is used in your code.
- Replace and store your secret safely. Learn here the best practices.
- Revoke and rotate this secret.
- If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.
To avoid such incidents in the future consider
- following these best practices for managing and storing secrets including API keys and other credentials
- install secret detection on pre-commit to catch secret before it leaves your machine and ease remediation.
🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThis PR adds signed CLI proxy authentication, introduces a soft-delete plugin and a new TaskForge sample, updates language and ORM internals for newer AST and typing behavior, adds date/time validation support, fixes several runtime regressions, and applies release, docs, and workspace version updates. ChangesCLI proxy and generation flow
Language, SDK, and Langium migration
ORM, validation, and API generation
Soft-delete plugin package
TaskForge sample app
Release metadata and repository maintenance
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Possibly related issues
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 12
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/cli/src/telemetry.ts (1)
31-53:⚠️ Potential issue | 🟠 Major | ⚡ Quick winAvoid collecting host metadata while telemetry is muted.
Class field initializers run before the constructor body, so
getMachineId(), OS/container probes, and Prisma-version file reads still happen even though Line 53 returns immediately. Move these values behind theif (this.mixpanel)path so muted telemetry does not collect device identifiers at all.🛡️ Proposed direction
- private readonly hostId = getMachineId(); - private readonly sessionid = randomUUID(); - private readonly _os_type = os.type(); - private readonly _os_release = os.release(); - private readonly _os_arch = os.arch(); - private readonly _os_version = os.version(); - private readonly _os_platform = os.platform(); - private readonly version = getVersion(); - private readonly prismaVersion = this.getPrismaVersion(); - private readonly isDocker = isDocker(); - private readonly isWsl = isWsl(); - private readonly isContainer = isInContainer(); - private readonly isCi = isInCi; + private sessionid: string | undefined;Then initialize the payload values inside
trackonly after confirmingthis.mixpanelexists.🤖 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 `@packages/cli/src/telemetry.ts` around lines 31 - 53, The class field initializers (hostId, _os_type, _os_release, _os_arch, _os_version, _os_platform, prismaVersion, isDocker, isWsl, isContainer) execute before the constructor body, so metadata collection happens even though telemetry is muted by the return statement on line 53. Remove or defer these field initializers from the class properties and instead initialize them lazily within the track method only after confirming this.mixpanel exists. Keep sessionid as a class field since it should be generated regardless, but move the environment/system probes behind the telemetry guard.
🤖 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 @.github/workflows/claude-code-review.yml:
- Line 32: The GitHub Action reference on the line using
anthropics/claude-code-action is pinned to a mutable tag (`@v1`), which
compromises workflow supply-chain security. Replace the mutable tag `@v1` with a
full commit SHA to ensure the exact version of the action is used and prevent
unexpected changes from tag updates.
In `@packages/cli/src/actions/proxy.ts`:
- Around line 402-409: When authentication is disabled (isAuthKeyEnabled is
false), the function should return the base client regardless of whether an
Authorization header is present or not. Currently, the condition on line 403
only returns the client when both !isAuthKeyEnabled AND !authHeader are true,
which allows an injected Authorization header to bypass the disabled auth check
and proceed to the policy client. Modify the condition to check only
!isAuthKeyEnabled and return the client immediately when auth is disabled,
preventing downstream policy restrictions from being applied when auth should
not be enforced.
- Around line 356-369: Include the HTTP method and request path in the signed
message to prevent signature replay attacks across different endpoints. Modify
the message construction (where payload, timestamp, and authorizationToken are
concatenated) to include req.method and a canonical representation of the path
from req.originalUrl in the signed payload, ensuring the signature is bound to
both the specific HTTP method and endpoint. Additionally, update any test
signing helper functions that generate signatures to include these same elements
in the identical order and format.
In `@packages/cli/src/index.ts`:
- Around line 278-283: The argParser callback for signatureToleranceSecs uses
parseInt which is too lenient and silently accepts malformed input like "60s"
(parsed as 60) or "1.5" (parsed as 1). Replace the parseInt-based validation
with stricter integer validation that ensures the entire input string represents
a valid non-negative integer, rejecting any input with trailing characters,
decimal points, or other malformed formats. This ensures the range check and
error message properly reflect what inputs are actually accepted.
In `@packages/language/src/validators/attribute-application-validator.ts`:
- Around line 85-86: The checkOnceInModel method call does not honor the
contextDataModel parameter when enforcing the @@@onceInModel constraint, instead
always deriving the model from getContainingDataModel(attr) within the method
implementation. This allows inherited attributes validated in a derived-model
context to bypass the check. Update the checkOnceInModel method signature to
accept and use the contextDataModel parameter, and modify the implementation to
validate against the provided contextDataModel rather than always deriving the
model from getContainingDataModel(attr). This ensures that inherited attributes
are properly checked within the context of their derived model to prevent
violations where a model ends up with multiple @@@onceInModel fields through
inheritance-only paths.
In `@README.md`:
- Around line 12-14: The img tag in the badge link on line 13 is missing an alt
attribute, which violates MD045 and reduces accessibility. Add an alt attribute
to the img element that displays the npm download badge for `@zenstackhq/language`
package. The alt text should be descriptive and concise, such as describing that
it shows the monthly download count for the package.
In `@samples/taskforge/README.md`:
- Around line 49-59: The fenced code block is missing a language identifier
which violates the MD040 linting rule. Add the language token "text" to the
opening fence by changing the triple backticks from ``` to ```text. This will
properly specify that the block contains plain text content and resolve the
markdown linting violation.
In `@samples/taskforge/src/auth.ts`:
- Around line 23-25: Remove the hardcoded fallback value from the secret
configuration in the auth setup. The line `secret:
process.env.BETTER_AUTH_SECRET ?? 'taskforge-dev-secret-0123456789abcdef'`
should be changed to only use the environment variable without the fallback
operator and default value, making the BETTER_AUTH_SECRET environment variable
required. This ensures the secret cannot be accidentally set to a predictable
default value and aligns with Better Auth's security model that explicitly
prevents using default secrets.
In `@samples/taskforge/src/cli.ts`:
- Around line 77-84: CLI option values for status and limit fields are passed
directly to ORM queries without validation, causing invalid inputs to generate
runtime query errors instead of immediate CLI validation errors. In the action
callbacks that handle these options, validate that status values match the
allowed enum set before passing to the ORM query, and validate that the limit
value converted via Number(opts.limit) is a positive integer (checking for NaN
and non-positive values). Perform this validation at the command boundary before
the ORM calls in the db.issue.findMany and similar database operations.
- Around line 76-83: The project slug lookup is ambiguous because the code
filters only by slug alone, but the schema defines slug as unique only within an
organization (composite unique constraint with organizationId and slug). In the
CLI action handler for the command at line 76 (and similarly at lines 107 and
183), modify the where clause to filter by both the organization slug and
project slug instead of project slug alone. Accept an organization slug
parameter in the command arguments and update the findMany query for db.issue to
include both organizationId (derived from orgSlug) and slug in the project
filter condition.
In `@samples/taskforge/zenstack/schema.zmodel`:
- Around line 509-519: The Reaction model currently allows invalid states where
both issueId and commentId can be null or both can be set, which violates the
intended one-target-only requirement. Add a model-level validation to the
Reaction model that enforces exactly one of issueId or commentId must be set at
any given time, rejecting states where both are null or both are non-null. This
can be implemented using ZModel's validation features (such as `@validate`
attribute or constraint rules) to ensure that reactions always reference exactly
one target, preventing orphaned or ambiguous rows.
In `@tests/e2e/orm/policy/isempty-function-pg.test.ts`:
- Around line 21-35: The test creates a policy test client using
createPolicyTestClient but never disconnects it, leaving the database connection
open and accumulating resources. After the expect statement completes, add a
cleanup step to disconnect the client by calling the appropriate disconnect or
close method on the client object. This should be done either at the end of the
test or preferably in an afterEach hook to ensure proper resource cleanup even
if the test fails.
---
Outside diff comments:
In `@packages/cli/src/telemetry.ts`:
- Around line 31-53: The class field initializers (hostId, _os_type,
_os_release, _os_arch, _os_version, _os_platform, prismaVersion, isDocker,
isWsl, isContainer) execute before the constructor body, so metadata collection
happens even though telemetry is muted by the return statement on line 53.
Remove or defer these field initializers from the class properties and instead
initialize them lazily within the track method only after confirming
this.mixpanel exists. Keep sessionid as a class field since it should be
generated regardless, but move the environment/system probes behind the
telemetry guard.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: d97f1a12-de1b-4b23-96da-101f7482227b
⛔ Files ignored due to path filters (4)
packages/language/src/generated/ast.tsis excluded by!**/generated/**packages/language/src/generated/grammar.tsis excluded by!**/generated/**packages/language/src/generated/module.tsis excluded by!**/generated/**pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (106)
.github/workflows/claude-code-review.ymlCLAUDE.mdREADME.mdpackage.jsonpackages/auth-adapters/better-auth/package.jsonpackages/auth-adapters/better-auth/src/schema-generator.tspackages/cli/package.jsonpackages/cli/src/actions/check.tspackages/cli/src/actions/db.tspackages/cli/src/actions/generate.tspackages/cli/src/actions/proxy.tspackages/cli/src/index.tspackages/cli/src/plugins/typescript.tspackages/cli/src/telemetry.tspackages/cli/test/db/pull.test.tspackages/cli/test/import-extension.test.tspackages/cli/test/proxy.test.tspackages/cli/test/ts-schema-gen.test.tspackages/cli/tsconfig.jsonpackages/clients/client-helpers/package.jsonpackages/clients/fetch-client/package.jsonpackages/clients/tanstack-query/package.jsonpackages/clients/tanstack-query/src/vue.tspackages/common-helpers/package.jsonpackages/config/eslint-config/package.jsonpackages/config/tsdown-config/package.jsonpackages/config/typescript-config/package.jsonpackages/config/vitest-config/package.jsonpackages/create-zenstack/package.jsonpackages/ide/vscode/package.jsonpackages/language/package.jsonpackages/language/res/stdlib.zmodelpackages/language/src/document.tspackages/language/src/factory/attribute.tspackages/language/src/factory/declaration.tspackages/language/src/factory/expression.tspackages/language/src/factory/primitives.tspackages/language/src/validators/attribute-application-validator.tspackages/language/src/zmodel-code-generator.tspackages/language/src/zmodel-linker.tspackages/language/src/zmodel-scope.tspackages/language/test/attribute-application.test.tspackages/language/tsconfig.jsonpackages/orm/package.jsonpackages/orm/src/client/contract.tspackages/orm/src/client/crud-types.tspackages/orm/src/client/crud/dialects/lateral-join-dialect-base.tspackages/orm/src/client/crud/dialects/postgresql.tspackages/orm/src/client/crud/dialects/sqlite.tspackages/orm/src/client/options.tspackages/orm/src/client/zod/factory.tspackages/plugins/policy/package.jsonpackages/plugins/policy/src/expression-transformer.tspackages/plugins/soft-delete/README.mdpackages/plugins/soft-delete/eslint.config.jspackages/plugins/soft-delete/package.jsonpackages/plugins/soft-delete/plugin.zmodelpackages/plugins/soft-delete/src/index.tspackages/plugins/soft-delete/src/plugin.tspackages/plugins/soft-delete/test/soft-delete.test.tspackages/plugins/soft-delete/test/tombstone-unique.test.tspackages/plugins/soft-delete/tsconfig.jsonpackages/plugins/soft-delete/tsdown.config.tspackages/plugins/soft-delete/vitest.config.tspackages/schema/package.jsonpackages/sdk/package.jsonpackages/sdk/src/index.tspackages/sdk/src/prisma/prisma-schema-generator.tspackages/sdk/src/tsconfig-utils.tspackages/server/package.jsonpackages/server/src/api/rpc/openapi.tspackages/server/test/openapi/rpc-openapi.test.tspackages/testtools/package.jsonpackages/testtools/src/client.tspackages/testtools/src/schema.tspackages/testtools/src/utils.tspackages/zod/package.jsonpackages/zod/src/utils.tspackages/zod/test/factory.test.tspackages/zod/test/schema/schema.tspackages/zod/test/schema/schema.zmodelpnpm-workspace.yamlsamples/orm/package.jsonsamples/sveltekit/package.jsonsamples/taskforge/README.mdsamples/taskforge/package.jsonsamples/taskforge/src/auth.tssamples/taskforge/src/cli.tssamples/taskforge/src/db.tssamples/taskforge/src/seed.tssamples/taskforge/tsconfig.jsonsamples/taskforge/zenstack/input.tssamples/taskforge/zenstack/models.tssamples/taskforge/zenstack/schema.tssamples/taskforge/zenstack/schema.zmodeltests/e2e/orm/client-api/find.test.tstests/e2e/orm/policy/isempty-function-pg.test.tstests/e2e/orm/validation/custom-validation.test.tstests/e2e/orm/validation/toplevel.test.tstests/e2e/package.jsontests/regression/package.jsontests/regression/test/issue-2669.test.tstests/regression/test/issue-2671.test.tstests/regression/test/issue-2718.test.tstests/runtimes/bun/package.jsontests/runtimes/edge-runtime/package.json
…2725) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The soft-delete plugin previously broke on models whose `@deletedAt` marker is inherited rather than declared directly on the queried model: - **Mixin models** (`@deletedAt` from a `type` mixin) now soft-delete correctly — the marker is flattened into the model's fields. - **Delegate (polymorphic) models** marked on the base now filter reads and rewrite deletes correctly. The marker physically lives on the base table, so `getDeletedAtField` skips inherited (`originModel`) markers, and the read filter walks the base chain to key the `IS NULL` predicate off the base table in the outer WHERE. - `transformJoin` skips any delegate-hierarchy member: those markers are always handled by `transformSelectQuery` (reconstruction joins via the outer WHERE, relation reads via their subquery FROM). Adding an ON-clause predicate on a LEFT reconstruction join would only null the joined columns and leak the soft-deleted row. Adds runtime tests for the mixin case, the delegate case (delete through both the concrete and base accessors), and a regression test ensuring updates can't touch an already soft-deleted delegate row. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Summary by CodeRabbit
New Features
@date,@time) and model field cardinality constraint (@@onceInModel)studioAuthKeywith signature verificationImprovements
_countsupport insideinclude(including filtered counts)Documentation