Skip to content

merge dev to main (v3.8.0)#2724

Merged
ymc9 merged 25 commits into
mainfrom
dev
Jun 18, 2026
Merged

merge dev to main (v3.8.0)#2724
ymc9 merged 25 commits into
mainfrom
dev

Conversation

@ymc9

@ymc9 ymc9 commented Jun 18, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • New Features

    • Soft-delete plugin for automatic row tombstoning
    • ISO date/time field validation attributes (@date, @time) and model field cardinality constraint (@@onceInModel)
    • CLI proxy/studio authentication via studioAuthKey with signature verification
    • Auto-detection of TypeScript import file extensions (Node16/NodeNext)
  • Improvements

    • Better query option typing and stricter omit handling
    • Nested relation _count support inside include (including filtered counts)
    • TanStack Query infinite pagination fixed
    • MySQL support for soft-delete tombstone uniqueness behavior
    • OpenAPI generation avoids dangling references when models are sliced
    • CLI telemetry fully disabled
  • Documentation

    • New TaskForge sample app and soft-delete plugin documentation

ymc9 and others added 22 commits May 30, 2026 22:25
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>
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

gitguardian Bot commented Jun 18, 2026

Copy link
Copy Markdown

⚠️ GitGuardian has uncovered 1 secret following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secret in your pull request
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
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secret safely. Learn here the best practices.
  3. Revoke and rotate this secret.
  4. 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


🦉 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.

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6cb46ac2-14ba-4f79-888a-804816ae96e2

📥 Commits

Reviewing files that changed from the base of the PR and between 8d46a7f and 897df21.

📒 Files selected for processing (2)
  • packages/plugins/soft-delete/src/plugin.ts
  • packages/plugins/soft-delete/test/soft-delete.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/plugins/soft-delete/src/plugin.ts

📝 Walkthrough

Walkthrough

This 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.

Changes

CLI proxy and generation flow

Layer / File(s) Summary
Signed proxy auth and policy client
packages/cli/src/actions/proxy.ts, packages/cli/src/index.ts, packages/cli/test/proxy.test.ts, packages/cli/package.json
The proxy command adds studioAuthKey and signature tolerance options, verifies Ed25519 request signatures, selects base vs policy-backed clients per request, and expands proxy auth coverage.
Generation path fixes and runtime behavior
packages/cli/src/actions/*, packages/cli/src/plugins/typescript.ts, packages/sdk/src/tsconfig-utils.ts, packages/cli/src/telemetry.ts, packages/cli/test/*, packages/cli/tsconfig.json
The CLI updates AST-derived source path lookup, auto-detects generated import file extensions from tsconfig, disables telemetry initialization, and adds related generation and watch-mode tests.

Language, SDK, and Langium migration

Layer / File(s) Summary
AST and scope migration
packages/language/src/..., packages/auth-adapters/better-auth/src/schema-generator.ts, packages/sdk/src/prisma/prisma-schema-generator.ts
AST factories, linker dispatch, scope computation, formatter URI handling, and schema generator references move to $type-based and updated Langium-compatible behavior.
Validation contracts and import detection utility
packages/language/res/stdlib.zmodel, packages/language/src/validators/datamodel-validator.ts, packages/language/test/*, packages/sdk/src/index.ts, packages/sdk/src/tsconfig-utils.ts, packages/language/package.json, packages/language/tsconfig.json
The language adds @@@onceInModel, @date, @time, isDate, and isTime, validates once-per-model field attributes, and the SDK exports a tsconfig-based import extension detector.

ORM, validation, and API generation

Layer / File(s) Summary
Query option typing and omit enforcement
packages/orm/src/client/{options.ts,contract.ts,zod/factory.ts,crud-types.ts}, tests/regression/test/issue-2671.test.ts
ORM client typing now projects query-relevant options into model operations and Zod generation, adds variance annotations, and restricts omitted-field selection when query-time override is disabled.
Runtime query behavior and API schemas
packages/clients/tanstack-query/src/vue.ts, packages/orm/src/client/crud/dialects/*, packages/plugins/policy/src/expression-transformer.ts, packages/server/src/api/rpc/openapi.ts, packages/server/test/openapi/*, tests/e2e/orm/*, tests/regression/test/{issue-2669,issue-2718}.test.ts
Runtime fixes cover Vue infinite query pagination, nested _count in relation includes, PostgreSQL array length SQL, enum in policy comparisons, and OpenAPI generation for excluded sliced models.
Date and time validation support
packages/zod/src/utils.ts, packages/zod/test/*, tests/e2e/orm/validation/*
Zod validation now handles @date, @time, isDate, and isTime, and tests update schema fixtures and validation expectations for date and time string fields.

Soft-delete plugin package

Layer / File(s) Summary
Plugin package and schema contract
packages/plugins/soft-delete/{package.json,plugin.zmodel,src/index.ts,README.md,tsconfig.json,tsdown.config.ts,vitest.config.ts,eslint.config.js}
A new @zenstackhq/plugin-soft-delete package is added with its @deletedAt schema contract, entrypoints, configs, and documentation.
Delete rewrite and filtering behavior
packages/plugins/soft-delete/src/plugin.ts, packages/testtools/src/*, packages/plugins/soft-delete/test/*
The runtime plugin rewrites supported deletes into timestamp updates, filters reads and updates by deletedAt, rejects unsupported joined deletes, validates marker fields, and adds CRUD and tombstone uniqueness tests.

TaskForge sample app

Layer / File(s) Summary
Schema and sample setup
samples/taskforge/{package.json,tsconfig.json,README.md}, samples/taskforge/zenstack/*
A new TaskForge sample adds package setup, documentation, a large SQLite schema, and generated ZenStack model and input artifacts.
Auth, client, CLI, and seeded workspace
samples/taskforge/src/{auth.ts,db.ts,cli.ts,seed.ts}
The sample wires Better-Auth to a SQLite ZenStack client, adds CLI commands for browsing and mutating workspace data, and seeds a complete dataset.

Release metadata and repository maintenance

Layer / File(s) Summary
Versions, catalogs, and docs
.github/workflows/claude-code-review.yml, README.md, CLAUDE.md, package.json, pnpm-workspace.yaml, packages/.../package.json, tests/.../package.json, samples/.../package.json
The repository updates package versions to 3.8.0, refreshes workspace catalog entries and overrides, updates the Claude review workflow action input, adjusts documentation, and applies related manifest changes.

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related issues

  • zenstackhq/zenstack#2713 — The Vue TanStack Query change now uses pageParam when building infinite-query request URLs, matching the pagination issue described there.

Possibly related PRs

  • zenstackhq/zenstack#2698 — Both PRs modify the CLI proxy auth flow, including signed requests, policy-backed client selection, and proxy test coverage.
  • zenstackhq/zenstack#2709 — Both PRs contain the same Langium 4 migration pattern across CLI, language, SDK, and schema-generation code paths.
  • zenstackhq/zenstack#2712 — Both PRs implement nested _count handling inside relation include paths and add regression coverage for that behavior.

Poem

🐇 I thumped through schemas in moonlit code,
with soft-delete carrots along the road.
I signed each proxy hop with care,
and taught time strings to validate fair.
TaskForge bloomed in a burrow bright—
release night hops with pure delight.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title 'merge dev to main (v3.8.0)' clearly indicates the primary objective—a version release merge—and appropriately references the release version (v3.8.0).
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 dev

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.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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 win

Avoid 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 the if (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 track only after confirming this.mixpanel exists.

🤖 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

📥 Commits

Reviewing files that changed from the base of the PR and between 55d7bc2 and 1af9b2b.

⛔ Files ignored due to path filters (4)
  • packages/language/src/generated/ast.ts is excluded by !**/generated/**
  • packages/language/src/generated/grammar.ts is excluded by !**/generated/**
  • packages/language/src/generated/module.ts is excluded by !**/generated/**
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (106)
  • .github/workflows/claude-code-review.yml
  • CLAUDE.md
  • README.md
  • package.json
  • packages/auth-adapters/better-auth/package.json
  • packages/auth-adapters/better-auth/src/schema-generator.ts
  • packages/cli/package.json
  • packages/cli/src/actions/check.ts
  • packages/cli/src/actions/db.ts
  • packages/cli/src/actions/generate.ts
  • packages/cli/src/actions/proxy.ts
  • packages/cli/src/index.ts
  • packages/cli/src/plugins/typescript.ts
  • packages/cli/src/telemetry.ts
  • packages/cli/test/db/pull.test.ts
  • packages/cli/test/import-extension.test.ts
  • packages/cli/test/proxy.test.ts
  • packages/cli/test/ts-schema-gen.test.ts
  • packages/cli/tsconfig.json
  • packages/clients/client-helpers/package.json
  • packages/clients/fetch-client/package.json
  • packages/clients/tanstack-query/package.json
  • packages/clients/tanstack-query/src/vue.ts
  • packages/common-helpers/package.json
  • packages/config/eslint-config/package.json
  • packages/config/tsdown-config/package.json
  • packages/config/typescript-config/package.json
  • packages/config/vitest-config/package.json
  • packages/create-zenstack/package.json
  • packages/ide/vscode/package.json
  • packages/language/package.json
  • packages/language/res/stdlib.zmodel
  • packages/language/src/document.ts
  • packages/language/src/factory/attribute.ts
  • packages/language/src/factory/declaration.ts
  • packages/language/src/factory/expression.ts
  • packages/language/src/factory/primitives.ts
  • packages/language/src/validators/attribute-application-validator.ts
  • packages/language/src/zmodel-code-generator.ts
  • packages/language/src/zmodel-linker.ts
  • packages/language/src/zmodel-scope.ts
  • packages/language/test/attribute-application.test.ts
  • packages/language/tsconfig.json
  • packages/orm/package.json
  • packages/orm/src/client/contract.ts
  • packages/orm/src/client/crud-types.ts
  • packages/orm/src/client/crud/dialects/lateral-join-dialect-base.ts
  • packages/orm/src/client/crud/dialects/postgresql.ts
  • packages/orm/src/client/crud/dialects/sqlite.ts
  • packages/orm/src/client/options.ts
  • packages/orm/src/client/zod/factory.ts
  • packages/plugins/policy/package.json
  • packages/plugins/policy/src/expression-transformer.ts
  • packages/plugins/soft-delete/README.md
  • packages/plugins/soft-delete/eslint.config.js
  • packages/plugins/soft-delete/package.json
  • packages/plugins/soft-delete/plugin.zmodel
  • packages/plugins/soft-delete/src/index.ts
  • packages/plugins/soft-delete/src/plugin.ts
  • packages/plugins/soft-delete/test/soft-delete.test.ts
  • packages/plugins/soft-delete/test/tombstone-unique.test.ts
  • packages/plugins/soft-delete/tsconfig.json
  • packages/plugins/soft-delete/tsdown.config.ts
  • packages/plugins/soft-delete/vitest.config.ts
  • packages/schema/package.json
  • packages/sdk/package.json
  • packages/sdk/src/index.ts
  • packages/sdk/src/prisma/prisma-schema-generator.ts
  • packages/sdk/src/tsconfig-utils.ts
  • packages/server/package.json
  • packages/server/src/api/rpc/openapi.ts
  • packages/server/test/openapi/rpc-openapi.test.ts
  • packages/testtools/package.json
  • packages/testtools/src/client.ts
  • packages/testtools/src/schema.ts
  • packages/testtools/src/utils.ts
  • packages/zod/package.json
  • packages/zod/src/utils.ts
  • packages/zod/test/factory.test.ts
  • packages/zod/test/schema/schema.ts
  • packages/zod/test/schema/schema.zmodel
  • pnpm-workspace.yaml
  • samples/orm/package.json
  • samples/sveltekit/package.json
  • samples/taskforge/README.md
  • samples/taskforge/package.json
  • samples/taskforge/src/auth.ts
  • samples/taskforge/src/cli.ts
  • samples/taskforge/src/db.ts
  • samples/taskforge/src/seed.ts
  • samples/taskforge/tsconfig.json
  • samples/taskforge/zenstack/input.ts
  • samples/taskforge/zenstack/models.ts
  • samples/taskforge/zenstack/schema.ts
  • samples/taskforge/zenstack/schema.zmodel
  • tests/e2e/orm/client-api/find.test.ts
  • tests/e2e/orm/policy/isempty-function-pg.test.ts
  • tests/e2e/orm/validation/custom-validation.test.ts
  • tests/e2e/orm/validation/toplevel.test.ts
  • tests/e2e/package.json
  • tests/regression/package.json
  • tests/regression/test/issue-2669.test.ts
  • tests/regression/test/issue-2671.test.ts
  • tests/regression/test/issue-2718.test.ts
  • tests/runtimes/bun/package.json
  • tests/runtimes/edge-runtime/package.json

Comment thread .github/workflows/claude-code-review.yml
Comment thread packages/cli/src/actions/proxy.ts
Comment thread packages/cli/src/actions/proxy.ts
Comment thread packages/cli/src/index.ts
Comment thread packages/language/src/validators/attribute-application-validator.ts Outdated
Comment thread samples/taskforge/src/auth.ts
Comment thread samples/taskforge/src/cli.ts
Comment thread samples/taskforge/src/cli.ts
Comment thread samples/taskforge/zenstack/schema.zmodel
Comment thread tests/e2e/orm/policy/isempty-function-pg.test.ts
ymc9 and others added 3 commits June 17, 2026 20:27
…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>
@ymc9 ymc9 merged commit 2f9fdc1 into main Jun 18, 2026
9 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.

4 participants