From e143a94f099beeb94eef3f308650da1f17da9134 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 11 Apr 2026 23:56:52 +0800 Subject: [PATCH 1/8] fix: exclude user-attached accesses from public policy detection --- .../src/lib/services/collections/policies/id-mapper-client.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/cli/src/lib/services/collections/policies/id-mapper-client.ts b/packages/cli/src/lib/services/collections/policies/id-mapper-client.ts index c5fe62ee..ba3cbe7a 100644 --- a/packages/cli/src/lib/services/collections/policies/id-mapper-client.ts +++ b/packages/cli/src/lib/services/collections/policies/id-mapper-client.ts @@ -120,6 +120,9 @@ export class PoliciesIdMapperClient extends IdMapperClient { filter: { _and: [ { roles: { role: { _null: true } } }, + // Exclude user-attached accesses (role=null, user=uuid) so they + // are not mistaken for the public policy access (role=null, user=null). + { roles: { user: { _null: true } } }, { _or: [ { roles: { sort: { _eq: 1 } } }, From 2ce8b0a9c93f94bc12fd162e4949376130ad155d Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 11 Apr 2026 23:58:02 +0800 Subject: [PATCH 2/8] fix: filter user-attached accesses from policy dump and add e2e coverage --- .../collections/policies/data-client.ts | 3 +- .../collections/policies/data-mapper.ts | 20 +++++++- .../push-with-user-policy-assignment.ts | 51 ++++++++++++++++++- 3 files changed, 69 insertions(+), 5 deletions(-) diff --git a/packages/cli/src/lib/services/collections/policies/data-client.ts b/packages/cli/src/lib/services/collections/policies/data-client.ts index 091d0a00..de441d8a 100644 --- a/packages/cli/src/lib/services/collections/policies/data-client.ts +++ b/packages/cli/src/lib/services/collections/policies/data-client.ts @@ -41,8 +41,9 @@ export class PoliciesDataClient extends DataClient { // When role-policy attachments sync is disabled, omit the roles fields // entirely from the dump so they are neither tracked nor diffed. // See https://github.com/tractr/directus-sync/issues/199 + // Include roles.user so we can detect and skip user-attached accesses. const extraFields = this.config.shouldSyncPolicyRoles() - ? ['*', 'roles.role', 'roles.sort'] + ? ['*', 'roles.role', 'roles.user', 'roles.sort'] : ['*']; return readPolicies( deepmerge>(query, { diff --git a/packages/cli/src/lib/services/collections/policies/data-mapper.ts b/packages/cli/src/lib/services/collections/policies/data-mapper.ts index 3cf1e519..703ffa45 100644 --- a/packages/cli/src/lib/services/collections/policies/data-mapper.ts +++ b/packages/cli/src/lib/services/collections/policies/data-mapper.ts @@ -1,8 +1,8 @@ -import { DataMapper, Field, IdMappers } from '../base'; +import { DataMapper, Field, IdMappers, WithSyncIdAndWithoutId } from '../base'; import { Container, Service } from 'typedi'; import { LoggerService } from '../../logger'; import { POLICIES_COLLECTION } from './constants'; -import { DirectusPolicy } from './interfaces'; +import { DirectusPolicy, DirectusPolicyAccess } from './interfaces'; import { RolesIdMapperClient } from '../roles'; import { ConfigService } from '../../config'; @@ -27,4 +27,20 @@ export class PoliciesDataMapper extends DataMapper { this.idMappers = {}; } } + + async mapIdsToSyncIdAndRemoveIgnoredFields( + items: WithSyncIdAndWithoutId[], + ): Promise[]> { + const filtered = items.map((item) => + Array.isArray(item.roles) + ? { + ...item, + roles: (item.roles as Partial[]).filter( + (a) => !(a.role === null && a.user != null), + ), + } + : item, + ); + return super.mapIdsToSyncIdAndRemoveIgnoredFields(filtered); + } } diff --git a/packages/e2e/spec/pull-diff-push/push-with-user-policy-assignment.ts b/packages/e2e/spec/pull-diff-push/push-with-user-policy-assignment.ts index 8306d7f6..bdb58c1c 100644 --- a/packages/e2e/spec/pull-diff-push/push-with-user-policy-assignment.ts +++ b/packages/e2e/spec/pull-diff-push/push-with-user-policy-assignment.ts @@ -1,5 +1,15 @@ -import { createUser, DirectusPolicy, readUser } from '@directus/sdk'; -import { Context, newPolicy, newRole, Schema } from '../helpers/index.js'; +import { + createUser, + DirectusPolicy, + readUser, +} from '@directus/sdk'; +import { + Context, + getDumpedSystemCollectionsContents, + newPolicy, + newRole, + Schema, +} from '../helpers/index.js'; export const pushWithUserPolicyAssignment = (context: Context) => { it('should preserve user policy assignments after push', async () => { @@ -54,4 +64,41 @@ export const pushWithUserPolicyAssignment = (context: Context) => { ); expect(finalUser.policies.map(extractPolicyId)).toContain(policy.id); }); + + it('should not include user-attached accesses in dump on pull', async () => { + const sync = await context.getSync( + 'temp/push-with-user-policy-assignment-pull-filter', + ); + const directus = context.getDirectus(); + const client = directus.get(); + + // Create a role and policy + const role = await newRole(client); + const policy = await newPolicy(client, role.id); + + // Assign the policy directly to a user (creates role=null, user=uuid access) + await client.request( + createUser({ + email: `user-policy-pull-${Date.now()}@example.com`, + password: 'password123', + role: role.id, + policies: [{ policy: policy.id, role: null, sort: 1 }], + } as Partial>), + ); + + // Pull + await sync.pull(); + + // Read the dump — user-attached accesses (role=null, user=uuid) must be absent + const { policies } = getDumpedSystemCollectionsContents(sync.getDumpPath()); + type DumpAccess = { role: string | null; user?: string | null }; + const userAttachedInDump = (policies ?? []).flatMap( + (p: Record) => + ( + (p.roles as unknown as DumpAccess[] | undefined) ?? [] + ).filter((r) => r.role === null && r.user != null), + ); + expect(userAttachedInDump.length).toBe(0); + }); + }; From 48b8d469d0b340faa3d5086dd74f9da2d5e6bc0a Mon Sep 17 00:00:00 2001 From: Edouard Demotes Date: Mon, 13 Apr 2026 17:11:47 -0400 Subject: [PATCH 3/8] fix: cast filtered policy items to include sync ID and exclude ignored fields --- .../cli/src/lib/services/collections/policies/data-mapper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/src/lib/services/collections/policies/data-mapper.ts b/packages/cli/src/lib/services/collections/policies/data-mapper.ts index 703ffa45..d5c78939 100644 --- a/packages/cli/src/lib/services/collections/policies/data-mapper.ts +++ b/packages/cli/src/lib/services/collections/policies/data-mapper.ts @@ -38,7 +38,7 @@ export class PoliciesDataMapper extends DataMapper { roles: (item.roles as Partial[]).filter( (a) => !(a.role === null && a.user != null), ), - } + } as WithSyncIdAndWithoutId : item, ); return super.mapIdsToSyncIdAndRemoveIgnoredFields(filtered); From 630b96f80dfb2b5ba5bafb3e09cc9607bac9dee2 Mon Sep 17 00:00:00 2001 From: Edouard Demotes Date: Mon, 13 Apr 2026 17:12:33 -0400 Subject: [PATCH 4/8] chore: run format --- .../services/collections/policies/data-mapper.ts | 4 ++-- .../push-with-user-policy-assignment.ts | 13 ++++--------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/packages/cli/src/lib/services/collections/policies/data-mapper.ts b/packages/cli/src/lib/services/collections/policies/data-mapper.ts index d5c78939..99522a17 100644 --- a/packages/cli/src/lib/services/collections/policies/data-mapper.ts +++ b/packages/cli/src/lib/services/collections/policies/data-mapper.ts @@ -33,12 +33,12 @@ export class PoliciesDataMapper extends DataMapper { ): Promise[]> { const filtered = items.map((item) => Array.isArray(item.roles) - ? { + ? ({ ...item, roles: (item.roles as Partial[]).filter( (a) => !(a.role === null && a.user != null), ), - } as WithSyncIdAndWithoutId + } as WithSyncIdAndWithoutId) : item, ); return super.mapIdsToSyncIdAndRemoveIgnoredFields(filtered); diff --git a/packages/e2e/spec/pull-diff-push/push-with-user-policy-assignment.ts b/packages/e2e/spec/pull-diff-push/push-with-user-policy-assignment.ts index bdb58c1c..8e0633d2 100644 --- a/packages/e2e/spec/pull-diff-push/push-with-user-policy-assignment.ts +++ b/packages/e2e/spec/pull-diff-push/push-with-user-policy-assignment.ts @@ -1,8 +1,4 @@ -import { - createUser, - DirectusPolicy, - readUser, -} from '@directus/sdk'; +import { createUser, DirectusPolicy, readUser } from '@directus/sdk'; import { Context, getDumpedSystemCollectionsContents, @@ -94,11 +90,10 @@ export const pushWithUserPolicyAssignment = (context: Context) => { type DumpAccess = { role: string | null; user?: string | null }; const userAttachedInDump = (policies ?? []).flatMap( (p: Record) => - ( - (p.roles as unknown as DumpAccess[] | undefined) ?? [] - ).filter((r) => r.role === null && r.user != null), + ((p.roles as unknown as DumpAccess[] | undefined) ?? []).filter( + (r) => r.role === null && r.user != null, + ), ); expect(userAttachedInDump.length).toBe(0); }); - }; From 2a0b6b4ea096d33bc49db1ad72b7b78588a49be9 Mon Sep 17 00:00:00 2001 From: Edouard Demotes Date: Mon, 13 Apr 2026 17:33:40 -0400 Subject: [PATCH 5/8] fix: add null user field to policy roles across multiple collections --- .../dumps/sources/default-updated/collections/policies.json | 2 ++ .../dependencies-operations-reversed/collections/policies.json | 2 ++ .../sources/dependencies-operations/collections/policies.json | 2 ++ .../collections/policies.json | 2 ++ .../collections/policies.json | 2 ++ .../dumps/sources/empty-collections/collections/policies.json | 2 ++ .../group-and-field-names-conflict/collections/policies.json | 2 ++ .../one-item-per-collection-updated/collections/policies.json | 3 +++ .../sources/one-item-per-collection/collections/policies.json | 3 +++ .../operations-dynamic-flow-id/collections/policies.json | 2 ++ .../dumps/sources/public-permissions/collections/policies.json | 2 ++ .../e2e/dumps/sources/seed-basic/collections/policies.json | 2 ++ .../e2e/dumps/sources/seed-files/collections/policies.json | 2 ++ .../e2e/dumps/sources/seed-users/collections/policies.json | 2 ++ .../snapshot-with-custom-model/collections/policies.json | 3 +++ .../snapshot-with-sync-id-map/collections/policies.json | 2 ++ 16 files changed, 35 insertions(+) diff --git a/packages/e2e/dumps/sources/default-updated/collections/policies.json b/packages/e2e/dumps/sources/default-updated/collections/policies.json index 08f22f86..778b9296 100644 --- a/packages/e2e/dumps/sources/default-updated/collections/policies.json +++ b/packages/e2e/dumps/sources/default-updated/collections/policies.json @@ -10,6 +10,7 @@ "roles": [ { "role": "_sync_default_admin_role", + "user": null, "sort": null } ], @@ -26,6 +27,7 @@ "roles": [ { "role": null, + "user": null, "sort": 1 } ], diff --git a/packages/e2e/dumps/sources/dependencies-operations-reversed/collections/policies.json b/packages/e2e/dumps/sources/dependencies-operations-reversed/collections/policies.json index e9ddc251..c6800145 100644 --- a/packages/e2e/dumps/sources/dependencies-operations-reversed/collections/policies.json +++ b/packages/e2e/dumps/sources/dependencies-operations-reversed/collections/policies.json @@ -10,6 +10,7 @@ "roles": [ { "role": "_sync_default_admin_role", + "user": null, "sort": null } ], @@ -26,6 +27,7 @@ "roles": [ { "role": null, + "user": null, "sort": 1 } ], diff --git a/packages/e2e/dumps/sources/dependencies-operations/collections/policies.json b/packages/e2e/dumps/sources/dependencies-operations/collections/policies.json index e9ddc251..c6800145 100644 --- a/packages/e2e/dumps/sources/dependencies-operations/collections/policies.json +++ b/packages/e2e/dumps/sources/dependencies-operations/collections/policies.json @@ -10,6 +10,7 @@ "roles": [ { "role": "_sync_default_admin_role", + "user": null, "sort": null } ], @@ -26,6 +27,7 @@ "roles": [ { "role": null, + "user": null, "sort": 1 } ], diff --git a/packages/e2e/dumps/sources/dependencies-settings-default-folder/collections/policies.json b/packages/e2e/dumps/sources/dependencies-settings-default-folder/collections/policies.json index e9ddc251..c6800145 100644 --- a/packages/e2e/dumps/sources/dependencies-settings-default-folder/collections/policies.json +++ b/packages/e2e/dumps/sources/dependencies-settings-default-folder/collections/policies.json @@ -10,6 +10,7 @@ "roles": [ { "role": "_sync_default_admin_role", + "user": null, "sort": null } ], @@ -26,6 +27,7 @@ "roles": [ { "role": null, + "user": null, "sort": 1 } ], diff --git a/packages/e2e/dumps/sources/dependencies-settings-default-role/collections/policies.json b/packages/e2e/dumps/sources/dependencies-settings-default-role/collections/policies.json index e9ddc251..c6800145 100644 --- a/packages/e2e/dumps/sources/dependencies-settings-default-role/collections/policies.json +++ b/packages/e2e/dumps/sources/dependencies-settings-default-role/collections/policies.json @@ -10,6 +10,7 @@ "roles": [ { "role": "_sync_default_admin_role", + "user": null, "sort": null } ], @@ -26,6 +27,7 @@ "roles": [ { "role": null, + "user": null, "sort": 1 } ], diff --git a/packages/e2e/dumps/sources/empty-collections/collections/policies.json b/packages/e2e/dumps/sources/empty-collections/collections/policies.json index e9ddc251..c6800145 100644 --- a/packages/e2e/dumps/sources/empty-collections/collections/policies.json +++ b/packages/e2e/dumps/sources/empty-collections/collections/policies.json @@ -10,6 +10,7 @@ "roles": [ { "role": "_sync_default_admin_role", + "user": null, "sort": null } ], @@ -26,6 +27,7 @@ "roles": [ { "role": null, + "user": null, "sort": 1 } ], diff --git a/packages/e2e/dumps/sources/group-and-field-names-conflict/collections/policies.json b/packages/e2e/dumps/sources/group-and-field-names-conflict/collections/policies.json index e9ddc251..c6800145 100644 --- a/packages/e2e/dumps/sources/group-and-field-names-conflict/collections/policies.json +++ b/packages/e2e/dumps/sources/group-and-field-names-conflict/collections/policies.json @@ -10,6 +10,7 @@ "roles": [ { "role": "_sync_default_admin_role", + "user": null, "sort": null } ], @@ -26,6 +27,7 @@ "roles": [ { "role": null, + "user": null, "sort": 1 } ], diff --git a/packages/e2e/dumps/sources/one-item-per-collection-updated/collections/policies.json b/packages/e2e/dumps/sources/one-item-per-collection-updated/collections/policies.json index 3a4043de..e65af66b 100644 --- a/packages/e2e/dumps/sources/one-item-per-collection-updated/collections/policies.json +++ b/packages/e2e/dumps/sources/one-item-per-collection-updated/collections/policies.json @@ -10,6 +10,7 @@ "roles": [ { "role": "_sync_default_admin_role", + "user": null, "sort": null } ], @@ -26,6 +27,7 @@ "roles": [ { "role": null, + "user": null, "sort": 1 } ], @@ -42,6 +44,7 @@ "roles": [ { "role": "52183adc-3e8e-4746-abd2-ee8dfc58efd5", + "user": null, "sort": 1 } ], diff --git a/packages/e2e/dumps/sources/one-item-per-collection/collections/policies.json b/packages/e2e/dumps/sources/one-item-per-collection/collections/policies.json index 221072d6..6c7a395b 100644 --- a/packages/e2e/dumps/sources/one-item-per-collection/collections/policies.json +++ b/packages/e2e/dumps/sources/one-item-per-collection/collections/policies.json @@ -10,6 +10,7 @@ "roles": [ { "role": "_sync_default_admin_role", + "user": null, "sort": null } ], @@ -26,6 +27,7 @@ "roles": [ { "role": null, + "user": null, "sort": 1 } ], @@ -42,6 +44,7 @@ "roles": [ { "role": "52183adc-3e8e-4746-abd2-ee8dfc58efd5", + "user": null, "sort": 1 } ], diff --git a/packages/e2e/dumps/sources/operations-dynamic-flow-id/collections/policies.json b/packages/e2e/dumps/sources/operations-dynamic-flow-id/collections/policies.json index e9ddc251..c6800145 100644 --- a/packages/e2e/dumps/sources/operations-dynamic-flow-id/collections/policies.json +++ b/packages/e2e/dumps/sources/operations-dynamic-flow-id/collections/policies.json @@ -10,6 +10,7 @@ "roles": [ { "role": "_sync_default_admin_role", + "user": null, "sort": null } ], @@ -26,6 +27,7 @@ "roles": [ { "role": null, + "user": null, "sort": 1 } ], diff --git a/packages/e2e/dumps/sources/public-permissions/collections/policies.json b/packages/e2e/dumps/sources/public-permissions/collections/policies.json index e9ddc251..c6800145 100644 --- a/packages/e2e/dumps/sources/public-permissions/collections/policies.json +++ b/packages/e2e/dumps/sources/public-permissions/collections/policies.json @@ -10,6 +10,7 @@ "roles": [ { "role": "_sync_default_admin_role", + "user": null, "sort": null } ], @@ -26,6 +27,7 @@ "roles": [ { "role": null, + "user": null, "sort": 1 } ], diff --git a/packages/e2e/dumps/sources/seed-basic/collections/policies.json b/packages/e2e/dumps/sources/seed-basic/collections/policies.json index e9ddc251..c6800145 100644 --- a/packages/e2e/dumps/sources/seed-basic/collections/policies.json +++ b/packages/e2e/dumps/sources/seed-basic/collections/policies.json @@ -10,6 +10,7 @@ "roles": [ { "role": "_sync_default_admin_role", + "user": null, "sort": null } ], @@ -26,6 +27,7 @@ "roles": [ { "role": null, + "user": null, "sort": 1 } ], diff --git a/packages/e2e/dumps/sources/seed-files/collections/policies.json b/packages/e2e/dumps/sources/seed-files/collections/policies.json index e9ddc251..c6800145 100644 --- a/packages/e2e/dumps/sources/seed-files/collections/policies.json +++ b/packages/e2e/dumps/sources/seed-files/collections/policies.json @@ -10,6 +10,7 @@ "roles": [ { "role": "_sync_default_admin_role", + "user": null, "sort": null } ], @@ -26,6 +27,7 @@ "roles": [ { "role": null, + "user": null, "sort": 1 } ], diff --git a/packages/e2e/dumps/sources/seed-users/collections/policies.json b/packages/e2e/dumps/sources/seed-users/collections/policies.json index e9ddc251..c6800145 100644 --- a/packages/e2e/dumps/sources/seed-users/collections/policies.json +++ b/packages/e2e/dumps/sources/seed-users/collections/policies.json @@ -10,6 +10,7 @@ "roles": [ { "role": "_sync_default_admin_role", + "user": null, "sort": null } ], @@ -26,6 +27,7 @@ "roles": [ { "role": null, + "user": null, "sort": 1 } ], diff --git a/packages/e2e/dumps/sources/snapshot-with-custom-model/collections/policies.json b/packages/e2e/dumps/sources/snapshot-with-custom-model/collections/policies.json index 163ee4c0..ef27d271 100644 --- a/packages/e2e/dumps/sources/snapshot-with-custom-model/collections/policies.json +++ b/packages/e2e/dumps/sources/snapshot-with-custom-model/collections/policies.json @@ -10,6 +10,7 @@ "roles": [ { "role": "_sync_default_admin_role", + "user": null, "sort": null } ], @@ -26,6 +27,7 @@ "roles": [ { "role": null, + "user": null, "sort": 1 } ], @@ -42,6 +44,7 @@ "roles": [ { "role": "5acb1b4a-64bb-484a-9e76-76ed9b13251e", + "user": null, "sort": 1 } ], diff --git a/packages/e2e/dumps/sources/snapshot-with-sync-id-map/collections/policies.json b/packages/e2e/dumps/sources/snapshot-with-sync-id-map/collections/policies.json index e9ddc251..c6800145 100644 --- a/packages/e2e/dumps/sources/snapshot-with-sync-id-map/collections/policies.json +++ b/packages/e2e/dumps/sources/snapshot-with-sync-id-map/collections/policies.json @@ -10,6 +10,7 @@ "roles": [ { "role": "_sync_default_admin_role", + "user": null, "sort": null } ], @@ -26,6 +27,7 @@ "roles": [ { "role": null, + "user": null, "sort": 1 } ], From 0537fdc277ea4fd39356c442659bd8e85d8033b1 Mon Sep 17 00:00:00 2001 From: Edouard Demotes Date: Mon, 13 Apr 2026 17:47:10 -0400 Subject: [PATCH 6/8] fix: include user field in policy roles for consistency across collections --- packages/e2e/spec/helpers/sdk/interfaces/policy.ts | 1 + packages/e2e/spec/helpers/utils/batch.ts | 2 +- packages/e2e/spec/pull-diff-push/pull-basic.ts | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/e2e/spec/helpers/sdk/interfaces/policy.ts b/packages/e2e/spec/helpers/sdk/interfaces/policy.ts index 1a9e8fdf..f4041877 100644 --- a/packages/e2e/spec/helpers/sdk/interfaces/policy.ts +++ b/packages/e2e/spec/helpers/sdk/interfaces/policy.ts @@ -3,6 +3,7 @@ export type FixPolicy = Omit & { name: string; roles: { role: string; + user: null; sort: number; }[]; }; diff --git a/packages/e2e/spec/helpers/utils/batch.ts b/packages/e2e/spec/helpers/utils/batch.ts index 63e304dc..c9ee6577 100644 --- a/packages/e2e/spec/helpers/utils/batch.ts +++ b/packages/e2e/spec/helpers/utils/batch.ts @@ -110,7 +110,7 @@ export async function createOneItemInEachSystemCollection( const [policy] = (await client.request( readPolicies({ filter: { id: policyRaw.id }, - fields: ['*', 'roles.role', 'roles.sort'], + fields: ['*', 'roles.role', 'roles.user', 'roles.sort'], // Todo: remove this once it is fixed in the SDK } as Query>), )) as unknown as FixPolicy>[]; diff --git a/packages/e2e/spec/pull-diff-push/pull-basic.ts b/packages/e2e/spec/pull-diff-push/pull-basic.ts index b3096b6c..3a4c2caa 100644 --- a/packages/e2e/spec/pull-diff-push/pull-basic.ts +++ b/packages/e2e/spec/pull-diff-push/pull-basic.ts @@ -144,6 +144,7 @@ export const pullBasic = (context: Context) => { policy.roles.map(async (role) => { return { role: (await directus.getByLocalId('roles', role.role)).sync_id, + user: role.user, sort: role.sort, }; }), From 6ae646876a0e78cee0a4ff0be148317115564283 Mon Sep 17 00:00:00 2001 From: Edouard Demotes Date: Mon, 13 Apr 2026 17:48:03 -0400 Subject: [PATCH 7/8] fix: run linter --- .../spec/pull-diff-push/push-with-user-policy-assignment.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/e2e/spec/pull-diff-push/push-with-user-policy-assignment.ts b/packages/e2e/spec/pull-diff-push/push-with-user-policy-assignment.ts index 8e0633d2..3be25514 100644 --- a/packages/e2e/spec/pull-diff-push/push-with-user-policy-assignment.ts +++ b/packages/e2e/spec/pull-diff-push/push-with-user-policy-assignment.ts @@ -87,10 +87,10 @@ export const pushWithUserPolicyAssignment = (context: Context) => { // Read the dump — user-attached accesses (role=null, user=uuid) must be absent const { policies } = getDumpedSystemCollectionsContents(sync.getDumpPath()); - type DumpAccess = { role: string | null; user?: string | null }; + interface DumpAccess { role: string | null; user?: string | null } const userAttachedInDump = (policies ?? []).flatMap( (p: Record) => - ((p.roles as unknown as DumpAccess[] | undefined) ?? []).filter( + ((p.roles as DumpAccess[] | undefined) ?? []).filter( (r) => r.role === null && r.user != null, ), ); From fcdaf3f422344fcbc25b466f3ea93c7a83f9d01e Mon Sep 17 00:00:00 2001 From: Edouard Demotes Date: Mon, 13 Apr 2026 17:48:27 -0400 Subject: [PATCH 8/8] chore: run format --- .../spec/pull-diff-push/push-with-user-policy-assignment.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/e2e/spec/pull-diff-push/push-with-user-policy-assignment.ts b/packages/e2e/spec/pull-diff-push/push-with-user-policy-assignment.ts index 3be25514..9c65e747 100644 --- a/packages/e2e/spec/pull-diff-push/push-with-user-policy-assignment.ts +++ b/packages/e2e/spec/pull-diff-push/push-with-user-policy-assignment.ts @@ -87,7 +87,10 @@ export const pushWithUserPolicyAssignment = (context: Context) => { // Read the dump — user-attached accesses (role=null, user=uuid) must be absent const { policies } = getDumpedSystemCollectionsContents(sync.getDumpPath()); - interface DumpAccess { role: string | null; user?: string | null } + interface DumpAccess { + role: string | null; + user?: string | null; + } const userAttachedInDump = (policies ?? []).flatMap( (p: Record) => ((p.roles as DumpAccess[] | undefined) ?? []).filter(