From 80c0bd6d68560b2beb2bfcddece9f8b3b8822089 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 17:50:05 -0700 Subject: [PATCH 1/3] [CI] Bump version 3.6.4 (#2624) Co-authored-by: ymc9 <104139426+ymc9@users.noreply.github.com> --- package.json | 2 +- packages/auth-adapters/better-auth/package.json | 2 +- packages/cli/package.json | 2 +- packages/clients/client-helpers/package.json | 2 +- packages/clients/tanstack-query/package.json | 2 +- packages/common-helpers/package.json | 2 +- packages/config/eslint-config/package.json | 2 +- packages/config/tsdown-config/package.json | 2 +- packages/config/typescript-config/package.json | 2 +- packages/config/vitest-config/package.json | 2 +- packages/create-zenstack/package.json | 2 +- packages/ide/vscode/package.json | 2 +- packages/language/package.json | 2 +- packages/orm/package.json | 2 +- packages/plugins/policy/package.json | 2 +- packages/schema/package.json | 2 +- packages/sdk/package.json | 2 +- packages/server/package.json | 2 +- packages/testtools/package.json | 2 +- packages/zod/package.json | 2 +- samples/orm/package.json | 2 +- tests/e2e/package.json | 2 +- tests/regression/package.json | 2 +- tests/runtimes/bun/package.json | 2 +- tests/runtimes/edge-runtime/package.json | 2 +- 25 files changed, 25 insertions(+), 25 deletions(-) diff --git a/package.json b/package.json index 1480b00f7..5637d83c2 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "zenstack-v3", "displayName": "ZenStack", "description": "ZenStack", - "version": "3.6.3", + "version": "3.6.4", "type": "module", "author": { "name": "ZenStack Team", diff --git a/packages/auth-adapters/better-auth/package.json b/packages/auth-adapters/better-auth/package.json index 5f153ee98..f823657b4 100644 --- a/packages/auth-adapters/better-auth/package.json +++ b/packages/auth-adapters/better-auth/package.json @@ -2,7 +2,7 @@ "name": "@zenstackhq/better-auth", "displayName": "ZenStack Better Auth Adapter", "description": "ZenStack Better Auth Adapter. This adapter is modified from better-auth's Prisma adapter.", - "version": "3.6.3", + "version": "3.6.4", "type": "module", "author": { "name": "ZenStack Team", diff --git a/packages/cli/package.json b/packages/cli/package.json index 8d6b5285a..baff7e04e 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -2,7 +2,7 @@ "name": "@zenstackhq/cli", "displayName": "ZenStack CLI", "description": "FullStack database toolkit with built-in access control and automatic API generation.", - "version": "3.6.3", + "version": "3.6.4", "type": "module", "author": { "name": "ZenStack Team", diff --git a/packages/clients/client-helpers/package.json b/packages/clients/client-helpers/package.json index 7f44c344b..50152b545 100644 --- a/packages/clients/client-helpers/package.json +++ b/packages/clients/client-helpers/package.json @@ -2,7 +2,7 @@ "name": "@zenstackhq/client-helpers", "displayName": "ZenStack Client Helpers", "description": "Helpers for implementing clients that consume ZenStack's CRUD service", - "version": "3.6.3", + "version": "3.6.4", "type": "module", "author": { "name": "ZenStack Team", diff --git a/packages/clients/tanstack-query/package.json b/packages/clients/tanstack-query/package.json index ee60b85bf..eaddd4aa4 100644 --- a/packages/clients/tanstack-query/package.json +++ b/packages/clients/tanstack-query/package.json @@ -2,7 +2,7 @@ "name": "@zenstackhq/tanstack-query", "displayName": "ZenStack TanStack Query Integration", "description": "TanStack Query Client for consuming ZenStack v3's CRUD service", - "version": "3.6.3", + "version": "3.6.4", "type": "module", "author": { "name": "ZenStack Team", diff --git a/packages/common-helpers/package.json b/packages/common-helpers/package.json index 02e89668b..2bebe6481 100644 --- a/packages/common-helpers/package.json +++ b/packages/common-helpers/package.json @@ -2,7 +2,7 @@ "name": "@zenstackhq/common-helpers", "displayName": "ZenStack Common Helpers", "description": "ZenStack Common Helpers", - "version": "3.6.3", + "version": "3.6.4", "type": "module", "author": { "name": "ZenStack Team", diff --git a/packages/config/eslint-config/package.json b/packages/config/eslint-config/package.json index 3ccf99d16..30bfa704e 100644 --- a/packages/config/eslint-config/package.json +++ b/packages/config/eslint-config/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/eslint-config", - "version": "3.6.3", + "version": "3.6.4", "type": "module", "private": true, "license": "MIT" diff --git a/packages/config/tsdown-config/package.json b/packages/config/tsdown-config/package.json index 3e1700ae0..d564522c6 100644 --- a/packages/config/tsdown-config/package.json +++ b/packages/config/tsdown-config/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/tsdown-config", - "version": "3.6.3", + "version": "3.6.4", "private": true, "type": "module", "license": "MIT", diff --git a/packages/config/typescript-config/package.json b/packages/config/typescript-config/package.json index 3481351f1..4e4548bea 100644 --- a/packages/config/typescript-config/package.json +++ b/packages/config/typescript-config/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/typescript-config", - "version": "3.6.3", + "version": "3.6.4", "private": true, "license": "MIT" } diff --git a/packages/config/vitest-config/package.json b/packages/config/vitest-config/package.json index 4d00103b8..d0124b17b 100644 --- a/packages/config/vitest-config/package.json +++ b/packages/config/vitest-config/package.json @@ -1,7 +1,7 @@ { "name": "@zenstackhq/vitest-config", "type": "module", - "version": "3.6.3", + "version": "3.6.4", "private": true, "license": "MIT", "exports": { diff --git a/packages/create-zenstack/package.json b/packages/create-zenstack/package.json index b581504e6..d26792dba 100644 --- a/packages/create-zenstack/package.json +++ b/packages/create-zenstack/package.json @@ -2,7 +2,7 @@ "name": "create-zenstack", "displayName": "Create ZenStack", "description": "Create a new ZenStack project", - "version": "3.6.3", + "version": "3.6.4", "type": "module", "author": { "name": "ZenStack Team", diff --git a/packages/ide/vscode/package.json b/packages/ide/vscode/package.json index 698845ccd..cacadcfa1 100644 --- a/packages/ide/vscode/package.json +++ b/packages/ide/vscode/package.json @@ -1,7 +1,7 @@ { "name": "zenstack-v3", "publisher": "zenstack", - "version": "3.6.3", + "version": "3.6.4", "displayName": "ZenStack V3 Language Tools", "description": "VSCode extension for ZenStack (v3) ZModel language", "private": true, diff --git a/packages/language/package.json b/packages/language/package.json index a958c6687..240103697 100644 --- a/packages/language/package.json +++ b/packages/language/package.json @@ -2,7 +2,7 @@ "name": "@zenstackhq/language", "displayName": "ZenStack Language Tooling", "description": "ZenStack ZModel language specification", - "version": "3.6.3", + "version": "3.6.4", "type": "module", "author": { "name": "ZenStack Team", diff --git a/packages/orm/package.json b/packages/orm/package.json index ce5181bd8..b192e72f5 100644 --- a/packages/orm/package.json +++ b/packages/orm/package.json @@ -2,7 +2,7 @@ "name": "@zenstackhq/orm", "displayName": "ZenStack ORM", "description": "ZenStack ORM", - "version": "3.6.3", + "version": "3.6.4", "type": "module", "author": { "name": "ZenStack Team", diff --git a/packages/plugins/policy/package.json b/packages/plugins/policy/package.json index 74a4d5ded..d0425fd04 100644 --- a/packages/plugins/policy/package.json +++ b/packages/plugins/policy/package.json @@ -2,7 +2,7 @@ "name": "@zenstackhq/plugin-policy", "displayName": "ZenStack Access Policy Plugin", "description": "ZenStack plugin that enforces access control policies defined in the schema", - "version": "3.6.3", + "version": "3.6.4", "type": "module", "author": { "name": "ZenStack Team", diff --git a/packages/schema/package.json b/packages/schema/package.json index e4e51f1b2..ca0f9323f 100644 --- a/packages/schema/package.json +++ b/packages/schema/package.json @@ -2,7 +2,7 @@ "name": "@zenstackhq/schema", "displayName": "ZenStack Schema Object Model", "description": "TypeScript representation of ZModel schema", - "version": "3.6.3", + "version": "3.6.4", "type": "module", "author": { "name": "ZenStack Team", diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 6dea9165b..a1e19d5c9 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -2,7 +2,7 @@ "name": "@zenstackhq/sdk", "displayName": "ZenStack SDK", "description": "Utilities for building ZenStack plugins", - "version": "3.6.3", + "version": "3.6.4", "type": "module", "author": { "name": "ZenStack Team", diff --git a/packages/server/package.json b/packages/server/package.json index 06d51b533..78f5691d8 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -2,7 +2,7 @@ "name": "@zenstackhq/server", "displayName": "ZenStack Automatic CRUD Server", "description": "ZenStack automatic CRUD API handlers and server adapters for popular frameworks", - "version": "3.6.3", + "version": "3.6.4", "type": "module", "author": { "name": "ZenStack Team", diff --git a/packages/testtools/package.json b/packages/testtools/package.json index 7d261bed8..3f02d2078 100644 --- a/packages/testtools/package.json +++ b/packages/testtools/package.json @@ -2,7 +2,7 @@ "name": "@zenstackhq/testtools", "displayName": "ZenStack Test Tools", "description": "ZenStack Test Tools", - "version": "3.6.3", + "version": "3.6.4", "type": "module", "author": { "name": "ZenStack Team", diff --git a/packages/zod/package.json b/packages/zod/package.json index 8f3d088d7..358514c43 100644 --- a/packages/zod/package.json +++ b/packages/zod/package.json @@ -2,7 +2,7 @@ "name": "@zenstackhq/zod", "displayName": "ZenStack Zod Integration", "description": "Automatically deriving Zod schemas from ZModel schemas", - "version": "3.6.3", + "version": "3.6.4", "type": "module", "author": { "name": "ZenStack Team", diff --git a/samples/orm/package.json b/samples/orm/package.json index 0868eb967..2e1a7278e 100644 --- a/samples/orm/package.json +++ b/samples/orm/package.json @@ -1,6 +1,6 @@ { "name": "sample-orm", - "version": "3.6.3", + "version": "3.6.4", "description": "", "main": "index.js", "private": true, diff --git a/tests/e2e/package.json b/tests/e2e/package.json index 931f99380..15992ff46 100644 --- a/tests/e2e/package.json +++ b/tests/e2e/package.json @@ -1,6 +1,6 @@ { "name": "e2e", - "version": "3.6.3", + "version": "3.6.4", "private": true, "type": "module", "scripts": { diff --git a/tests/regression/package.json b/tests/regression/package.json index 3907431f5..e74dd7a31 100644 --- a/tests/regression/package.json +++ b/tests/regression/package.json @@ -1,6 +1,6 @@ { "name": "regression", - "version": "3.6.3", + "version": "3.6.4", "private": true, "type": "module", "scripts": { diff --git a/tests/runtimes/bun/package.json b/tests/runtimes/bun/package.json index d30c900bd..726e8fa27 100644 --- a/tests/runtimes/bun/package.json +++ b/tests/runtimes/bun/package.json @@ -1,6 +1,6 @@ { "name": "bun-e2e", - "version": "3.6.3", + "version": "3.6.4", "private": true, "type": "module", "scripts": { diff --git a/tests/runtimes/edge-runtime/package.json b/tests/runtimes/edge-runtime/package.json index 871decac1..a87e0322b 100644 --- a/tests/runtimes/edge-runtime/package.json +++ b/tests/runtimes/edge-runtime/package.json @@ -1,6 +1,6 @@ { "name": "edge-runtime-e2e", - "version": "3.6.3", + "version": "3.6.4", "private": true, "type": "module", "scripts": { From 0bc1f4849d8641d82c392e3e75fbeed762a744bc Mon Sep 17 00:00:00 2001 From: Pavel Kudinov Date: Tue, 28 Apr 2026 09:12:13 +0800 Subject: [PATCH 2/3] fix(better-auth): array support (#2617) --- .../auth-adapters/better-auth/src/adapter.ts | 28 +---- .../auth-adapters/better-auth/src/config.ts | 36 ++++++ .../better-auth/src/schema-generator.ts | 13 +- .../better-auth/test/adapter.test.ts | 115 ++++++++++++++++++ 4 files changed, 163 insertions(+), 29 deletions(-) create mode 100644 packages/auth-adapters/better-auth/src/config.ts create mode 100644 packages/auth-adapters/better-auth/test/adapter.test.ts diff --git a/packages/auth-adapters/better-auth/src/adapter.ts b/packages/auth-adapters/better-auth/src/adapter.ts index cc5d850c3..27b2d4f59 100644 --- a/packages/auth-adapters/better-auth/src/adapter.ts +++ b/packages/auth-adapters/better-auth/src/adapter.ts @@ -1,5 +1,5 @@ import type { BetterAuthOptions } from '@better-auth/core'; -import type { DBAdapter, DBAdapterDebugLogOption, Where } from '@better-auth/core/db/adapter'; +import type { DBAdapter, Where } from '@better-auth/core/db/adapter'; import { BetterAuthError } from '@better-auth/core/error'; import type { ClientContract, ModelOperations, UpdateInput } from '@zenstackhq/orm'; import type { GetModels, SchemaDef } from '@zenstackhq/orm/schema'; @@ -8,30 +8,9 @@ import { type AdapterFactoryCustomizeAdapterCreator, type AdapterFactoryOptions, } from 'better-auth/adapters'; +import { getSupportsArrays, type AdapterConfig } from './config'; -/** - * Options for the ZenStack adapter factory. - */ -export interface AdapterConfig { - /** - * Database provider - */ - provider: 'sqlite' | 'postgresql'; - - /** - * Enable debug logs for the adapter - * - * @default false - */ - debugLogs?: DBAdapterDebugLogOption | undefined; - - /** - * Use plural table names - * - * @default false - */ - usePlural?: boolean | undefined; -} +export type { AdapterConfig } from './config'; /** * Create a Better-Auth adapter for ZenStack ORM. @@ -220,6 +199,7 @@ export const zenstackAdapter = (db: ClientContract db.$transaction((tx) => { const adapter = createAdapterFactory({ diff --git a/packages/auth-adapters/better-auth/src/config.ts b/packages/auth-adapters/better-auth/src/config.ts new file mode 100644 index 000000000..a3eb42dc2 --- /dev/null +++ b/packages/auth-adapters/better-auth/src/config.ts @@ -0,0 +1,36 @@ +import type { DBAdapterDebugLogOption } from '@better-auth/core/db/adapter'; + +/** + * Options for the ZenStack adapter factory. + */ +export interface AdapterConfig { + /** + * Database provider + */ + provider: 'sqlite' | 'postgresql'; + + /** + * Enable debug logs for the adapter + * + * @default false + */ + debugLogs?: DBAdapterDebugLogOption | undefined; + + /** + * Use plural table names + * + * @default false + */ + usePlural?: boolean | undefined; + + /** + * Preserve Better Auth array fields as native database arrays. + * + * Defaults to true for PostgreSQL and false for SQLite. + */ + supportsArrays?: boolean | undefined; +} + +export function getSupportsArrays(config: AdapterConfig) { + return config.supportsArrays ?? config.provider === 'postgresql'; +} diff --git a/packages/auth-adapters/better-auth/src/schema-generator.ts b/packages/auth-adapters/better-auth/src/schema-generator.ts index 1c31b4dd2..dee102dc2 100644 --- a/packages/auth-adapters/better-auth/src/schema-generator.ts +++ b/packages/auth-adapters/better-auth/src/schema-generator.ts @@ -26,7 +26,7 @@ import type { DBAdapterSchemaCreation } from 'better-auth/adapters'; import type { BetterAuthDBSchema, DBFieldAttribute, DBFieldType } from 'better-auth/db'; import fs from 'node:fs'; import { match } from 'ts-pattern'; -import type { AdapterConfig } from './adapter'; +import { getSupportsArrays, type AdapterConfig } from './config'; export async function generateSchema( file: string | undefined, @@ -95,6 +95,7 @@ async function updateSchema( let changed = false; + const supportsArrays = getSupportsArrays(config); for (const [name, table] of Object.entries(tables)) { const c = addOrUpdateModel( name, @@ -102,6 +103,7 @@ async function updateSchema( zmodel, tables, toManyRelations, + supportsArrays, !!options.advanced?.database?.useNumberId, ); changed = changed || c; @@ -251,15 +253,15 @@ function initializeZmodel(config: AdapterConfig) { return zmodel; } -function getMappedFieldType({ bigint, type }: DBFieldAttribute) { +function getMappedFieldType({ bigint, type }: DBFieldAttribute, supportsArrays: boolean) { return match(type) .with('string', () => ({ type: 'String' })) .with('number', () => (bigint ? { type: 'BigInt' } : { type: 'Int' })) .with('boolean', () => ({ type: 'Boolean' })) .with('date', () => ({ type: 'DateTime' })) .with('json', () => ({ type: 'Json' })) - .with('string[]', () => ({ type: 'String', array: true })) - .with('number[]', () => ({ type: 'Int', array: true })) + .with('string[]', () => (supportsArrays ? { type: 'String', array: true } : { type: 'Json' })) + .with('number[]', () => (supportsArrays ? { type: 'Int', array: true } : { type: 'Json' })) .when( (v) => Array.isArray(v) && v.every((e) => typeof e === 'string'), () => { @@ -278,6 +280,7 @@ function addOrUpdateModel( zmodel: Model, tables: BetterAuthDBSchema, toManyRelations: Map>, + supportsArrays: boolean, numericId: boolean, ): boolean { let changed = false; @@ -305,7 +308,7 @@ function addOrUpdateModel( if (!field.references) { // scalar field - const { array, type } = getMappedFieldType(field); + const { array, type } = getMappedFieldType(field, supportsArrays); const df: DataField = { $type: 'DataField', diff --git a/packages/auth-adapters/better-auth/test/adapter.test.ts b/packages/auth-adapters/better-auth/test/adapter.test.ts new file mode 100644 index 000000000..41926886e --- /dev/null +++ b/packages/auth-adapters/better-auth/test/adapter.test.ts @@ -0,0 +1,115 @@ +import type { BetterAuthOptions } from '@better-auth/core'; +import type { BetterAuthDBSchema } from 'better-auth/db'; +import fs from 'node:fs'; +import path from 'node:path'; +import tmp from 'tmp'; +import { describe, expect, it } from 'vitest'; +import { type AdapterConfig, zenstackAdapter } from '../src/adapter'; +import { generateSchema } from '../src/schema-generator'; + +const oauthClientSchema = { + oauthClient: { + modelName: 'oauthClient', + fields: { + name: { + type: 'string', + required: true, + }, + scopes: { + type: 'string[]', + required: true, + }, + retryDelays: { + type: 'number[]', + required: false, + }, + }, + }, +} satisfies BetterAuthDBSchema; + +function makeAuthOptions() { + return { + plugins: [ + { + id: 'oauth-provider', + schema: oauthClientSchema, + }, + ], + } as unknown as BetterAuthOptions; +} + +function makeDb(captured: { createData?: Record }) { + return { + oauthClient: { + create: async ({ data }: { data: Record }) => { + captured.createData = data; + return data; + }, + }, + $transaction: async (cb: (tx: unknown) => Promise) => cb(makeDb(captured)), + }; +} + +async function createOauthClient(config: AdapterConfig) { + const captured: { createData?: Record } = {}; + const adapter = zenstackAdapter(makeDb(captured) as any, config)(makeAuthOptions()); + + await adapter.create({ + model: 'oauthClient', + data: { + id: 'client-1', + name: 'client', + scopes: ['openid', 'profile'], + retryDelays: [1, 2], + }, + forceAllowId: true, + }); + + return captured.createData; +} + +async function generateOauthClientSchema(config: AdapterConfig) { + const { name: workDir, removeCallback } = tmp.dirSync({ unsafeCleanup: true }); + const schemaPath = path.join(workDir, 'schema.zmodel'); + + try { + const result = await generateSchema(schemaPath, oauthClientSchema, config, makeAuthOptions()); + return result.code; + } finally { + if (fs.existsSync(workDir)) { + removeCallback(); + } + } +} + +describe('ZenStack Better Auth adapter', () => { + it('preserves native array inputs for PostgreSQL (#2615)', async () => { + const data = await createOauthClient({ provider: 'postgresql' }); + + expect(data?.scopes).toEqual(['openid', 'profile']); + expect(data?.retryDelays).toEqual([1, 2]); + }); + + it('serializes array inputs when native arrays are disabled (#2615)', async () => { + const data = await createOauthClient({ provider: 'postgresql', supportsArrays: false }); + + expect(data?.scopes).toBe(JSON.stringify(['openid', 'profile'])); + expect(data?.retryDelays).toBe(JSON.stringify([1, 2])); + }); + + it('generates native array fields when the adapter supports arrays (#2615)', async () => { + const schema = await generateOauthClientSchema({ provider: 'postgresql' }); + + expect(schema).toMatch(/scopes\s+String\[\]/); + expect(schema).toMatch(/retryDelays\s+Int\[\]\?/); + }); + + it('generates JSON fields when the adapter does not support arrays (#2615)', async () => { + const schema = await generateOauthClientSchema({ provider: 'sqlite' }); + + expect(schema).toMatch(/scopes\s+Json/); + expect(schema).toMatch(/retryDelays\s+Json\?/); + expect(schema).not.toMatch(/scopes\s+String\[\]/); + expect(schema).not.toMatch(/retryDelays\s+Int\[\]/); + }); +}); From d30ebade7f88ec8e7a3a7badce12450b2af0bb8d Mon Sep 17 00:00:00 2001 From: Yiming Cao Date: Mon, 27 Apr 2026 18:23:37 -0700 Subject: [PATCH 3/3] fix(policy): resolve inherited fields in delegate sub-type create policy checks (#2623) Co-authored-by: Claude Sonnet 4.6 --- .../policy/src/expression-transformer.ts | 10 ++-- tests/regression/test/issue-2620.test.ts | 51 +++++++++++++++++++ 2 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 tests/regression/test/issue-2620.test.ts diff --git a/packages/plugins/policy/src/expression-transformer.ts b/packages/plugins/policy/src/expression-transformer.ts index e3f378f5d..565afe875 100644 --- a/packages/plugins/policy/src/expression-transformer.ts +++ b/packages/plugins/policy/src/expression-transformer.ts @@ -912,17 +912,15 @@ export class ExpressionTransformer { const tableName = context.alias ?? context.modelOrType; - // "create" policies evaluate table from "VALUES" node so no join from delegate bases are - // created and thus we should directly use the model table name - if (context.operation === 'create') { - return ReferenceNode.create(ColumnNode.create(column), TableNode.create(tableName)); - } - const fieldDef = QueryUtils.requireField(this.schema, context.modelOrType, column); if (!fieldDef.originModel || fieldDef.originModel === context.modelOrType) { return ReferenceNode.create(ColumnNode.create(column), TableNode.create(tableName)); } + // For inherited fields in delegate sub-types, use a correlated subquery against the + // base table. For create operations the VALUES table contains the sub-type's own + // fields and its id FK, so the subquery can look up the base record (already inserted + // in the same transaction) to resolve inherited field values correctly. return this.buildDelegateBaseFieldSelect(context.modelOrType, tableName, column, fieldDef.originModel); } diff --git a/tests/regression/test/issue-2620.test.ts b/tests/regression/test/issue-2620.test.ts new file mode 100644 index 000000000..7ddbc5f1a --- /dev/null +++ b/tests/regression/test/issue-2620.test.ts @@ -0,0 +1,51 @@ +import { createPolicyTestClient } from '@zenstackhq/testtools'; +import { describe, expect, it } from 'vitest'; + +// https://github.com/zenstackhq/zenstack/issues/2620 +describe('Regression: create delegate sub-model with policy referencing inherited field', () => { + const schema = ` +type Auth { + id String @id + organizationId String? + @@auth +} + +model Fund { + id String @id @default(uuid()) + organizationId String + type String + + @@delegate(type) + @@allow('all', auth().organizationId == organizationId) +} + +model GeneralFund extends Fund { + balance Float @default(0) + + @@allow('all', auth().organizationId == organizationId) +} +`; + + it('should allow creating a GeneralFund when auth organizationId matches', async () => { + const db = await createPolicyTestClient(schema); + const orgId = 'org-1'; + const authDb = db.$setAuth({ id: 'user-1', organizationId: orgId }); + + await expect( + authDb.generalFund.create({ + data: { organizationId: orgId }, + }), + ).resolves.toMatchObject({ organizationId: orgId }); + }); + + it('should deny creating a GeneralFund when auth organizationId does not match', async () => { + const db = await createPolicyTestClient(schema); + const authDb = db.$setAuth({ id: 'user-1', organizationId: 'org-1' }); + + await expect( + authDb.generalFund.create({ + data: { organizationId: 'org-2' }, + }), + ).toBeRejectedByPolicy(); + }); +});