Skip to content

Conversation

@guillaumejacquart
Copy link
Contributor

Summary

This PR changes the way we fetch access controlled credentials and workflows.
Before:

  • get all allowed resource ids (from shared entity and project relations)
  • fetch the resources according to those ids
    After:
  • build the query builder to fetch them all at once, introducing an access control object to help build the query

Related Linear tickets, Github issues, and Community forum posts

https://linear.app/n8n/issue/IAM-159/unusable-workflow-and-credentials-listing-at-large-scale#comment-8f150397

Review / Merge checklist

  • PR title and summary are descriptive. (conventions)
  • Docs updated or follow-up ticket created.
  • Tests included.
  • PR Labeled with release/backport (if the PR is an urgent fix that needs to be backported)

@guillaumejacquart guillaumejacquart changed the title Change access controlled credentials and workflows fetching to preven… chore(core): Improve access controlled credentials and workflows fetching Jan 29, 2026
@codecov
Copy link

codecov bot commented Jan 29, 2026

❌ 7 Tests Failed:

Tests completed Failed Passed Skipped
18553 7 18546 0
View the top 3 failed test(s) by shortest run time
GET /workflows filter should filter by personal project and return only workflows where the user is owner
Stack Traces | 0.08s run time
Error: expect(received).toHaveLength(expected)

Expected length: 1
Received length: 2
Received array:  [{"active": false, "activeVersionId": null, "createdAt": "2026-01-29T10:33:55.719Z", "description": null, "homeProject": {"icon": null, "id": "BUvlQ9gJUZll3oad", "name": "mcamirsr 9hcje <kag9ax@cra2105z.net>", "type": "personal"}, "id": "DzgRa5OItyfJXzKF", "isArchived": false, "name": "First", "parentFolder": null, "settings": {}, "sharedWithProjects": [], "tags": [], "updatedAt": "2026-01-29T10:33:55.719Z", "versionId": "49efdf50-ee4f-4169-8012-c68a6bbb0047"}, {"active": false, "activeVersionId": null, "createdAt": "2026-01-29T10:33:55.720Z", "description": null, "homeProject": {"icon": null, "id": "9Pz4ZyInfIh5NbpH", "name": "cf2sek ti6ossd <kywkih@rcmsty6.org>", "type": "personal"}, "id": "KrrhyYP6Qmoz15hj", "isArchived": false, "name": "Second", "parentFolder": null, "settings": {}, "sharedWithProjects": [{"icon": null, "id": "BUvlQ9gJUZll3oad", "name": "mcamirsr 9hcje <kag9ax@cra2105z.net>", "type": "personal"}], "tags": [], "updatedAt": "2026-01-29T10:33:55.720Z", "versionId": "60da6931-e29d-4c42-b6b3-d656d6f29818"}]
    at Object.<anonymous> (.../integration/workflows/workflows.controller.test.ts:1328:32)
    at processTicksAndRejections (node:internal/process/task_queues:105:5)
GET /workflows?includeFolders=true should return workflows with scopes and folders when ?includeScopes=true
Stack Traces | 0.094s run time
Error: expect(received).toBe(expected) // Object.is equality

Expected: 3
Received: 4
    at Object.<anonymous> (.../integration/workflows/workflows.controller.test.ts:2290:38)
    at processTicksAndRejections (node:internal/process/task_queues:105:5)
GET /workflows?onlySharedWithMe=true should return only workflows shared with me
Stack Traces | 0.111s run time
Error: expect(received).toEqual(expected) // deep equality

- Expected  - 1
+ Received  + 1

@@ -1,7 +1,7 @@
  Object {
-   "count": 1,
+   "count": 3,
    "data": ArrayContaining [
      ObjectContaining {
        "active": false,
        "activeVersionId": null,
        "createdAt": Any<String>,
    at Object.<anonymous> (.../integration/workflows/workflows.controller.test.ts:2005:25)
    at processTicksAndRejections (node:internal/process/task_queues:105:5)
POST /credentials/test should return only credentials shared with me when ?onlySharedWithMe=true (owner)
Stack Traces | 0.125s run time
Error: expect(received).toHaveLength(expected)

Expected length: 0
Received length: 1
Received array:  [{"createdAt": "2026-01-29T10:34:23.905Z", "homeProject": {"icon": null, "id": "mGCXcxayGTtfMGW1", "name": "zdtfd6z n7lc4fuv <rfsrb@hnje.com>", "type": "personal"}, "id": "yzGUsiLc6og0ODRY", "isGlobal": false, "isManaged": false, "isResolvable": false, "name": "xvanykdk", "resolvableAllowFallback": false, "resolverId": null, "sharedWithProjects": [{"icon": null, "id": "hPglCEQXvbyB4MG8", "name": "eoaroq ehe1zb5v <0e9f@ukfndxwt.io>", "type": "personal"}], "type": "githubApi", "updatedAt": "2026-01-29T10:34:23.905Z"}]
    at Object.<anonymous> (.../integration/credentials/credentials.api.test.ts:1872:30)
    at processTicksAndRejections (node:internal/process/task_queues:105:5)
POST /credentials/test should return only credentials shared with me when ?onlySharedWithMe=true (member)
Stack Traces | 0.13s run time
Error: expect(received).toHaveLength(expected)

Expected length: 1
Received length: 3
Received array:  [{"createdAt": "2026-01-29T10:34:24.186Z", "homeProject": {"icon": null, "id": "y69TKovLwrJfCdD3", "name": "utmb01ap g06gtp <jy9dlj@9lywnyr.io>", "type": "personal"}, "id": "j670Vf56i9OjGgU0", "isGlobal": false, "isManaged": false, "isResolvable": false, "name": "wxzipmj", "resolvableAllowFallback": false, "resolverId": null, "sharedWithProjects": [], "type": "githubApi", "updatedAt": "2026-01-29T10:34:24.186Z"}, {"createdAt": "2026-01-29T10:34:24.189Z", "homeProject": {"icon": null, "id": "y69TKovLwrJfCdD3", "name": "utmb01ap g06gtp <jy9dlj@9lywnyr.io>", "type": "personal"}, "id": "LDHG7lsLaKZkITpF", "isGlobal": false, "isManaged": false, "isResolvable": false, "name": "jwbcsad", "resolvableAllowFallback": false, "resolverId": null, "sharedWithProjects": [], "type": "githubApi", "updatedAt": "2026-01-29T10:34:24.189Z"}, {"createdAt": "2026-01-29T10:34:24.195Z", "homeProject": {"icon": null, "id": "Bfh1l03KJuownDKm", "name": "hldh ngm5 <24qnc@9e35t.net>", "type": "personal"}, "id": "clsunasMlZ3I4nLh", "isGlobal": false, "isManaged": false, "isResolvable": false, "name": "mmzl", "resolvableAllowFallback": false, "resolverId": null, "sharedWithProjects": [{"icon": null, "id": "y69TKovLwrJfCdD3", "name": "utmb01ap g06gtp <jy9dlj@9lywnyr.io>", "type": "personal"}], "type": "githubApi", "updatedAt": "2026-01-29T10:34:24.195Z"}]
    at Object.<anonymous> (.../integration/credentials/credentials.api.test.ts:1930:30)
    at processTicksAndRejections (node:internal/process/task_queues:105:5)
GET /credentials should return only relevant creds for member
Stack Traces | 0.143s run time
Error: expect(received).toHaveLength(expected)

Expected length: 1
Received length: 0
Received array:  []
    at Object.<anonymous> (.../integration/credentials/credentials.api.ee.test.ts:243:48)
    at processTicksAndRejections (node:internal/process/task_queues:105:5)
POST /credentials/test should return only credentials shared with me when ?onlySharedWithMe=true (admin)
Stack Traces | 0.151s run time
Error: expect(received).toHaveLength(expected)

Expected length: 0
Received length: 1
Received array:  [{"createdAt": "2026-01-29T10:34:24.058Z", "homeProject": {"icon": null, "id": "NAgT2URdJEGc83rx", "name": "ztjdh y503kzso <qybiv@ltv7y8ik.org>", "type": "personal"}, "id": "Xpd8M4etY7doAjsZ", "isGlobal": false, "isManaged": false, "isResolvable": false, "name": "oc5xh4a", "resolvableAllowFallback": false, "resolverId": null, "sharedWithProjects": [{"icon": null, "id": "7DvKXifN9Vf21jer", "name": "hbdw1 ehqsbtl <zriyy6df@mcl1icqz.net>", "type": "personal"}], "type": "githubApi", "updatedAt": "2026-01-29T10:34:24.058Z"}]
    at Object.<anonymous> (.../integration/credentials/credentials.api.test.ts:1903:30)
    at processTicksAndRejections (node:internal/process/task_queues:105:5)

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

@blacksmith-sh
Copy link

blacksmith-sh bot commented Jan 29, 2026

Found 21 test failures on Blacksmith runners:

Failures

Test View Logs
GET /credentials/POST /credentials/
test should return only credentials shared with me when ?onlySharedWithMe=true (admin)
View Logs
GET /credentials/POST /credentials/
test should return only credentials shared with me when ?onlySharedWithMe=true (admin)
View Logs
GET /credentials/POST /credentials/
test should return only credentials shared with me when ?onlySharedWithMe=true (admin)
View Logs
GET /credentials/POST /credentials/
test should return only credentials shared with me when ?onlySharedWithMe=true (member)
View Logs
GET /credentials/POST /credentials/
test should return only credentials shared with me when ?onlySharedWithMe=true (member)
View Logs
GET /credentials/POST /credentials/
test should return only credentials shared with me when ?onlySharedWithMe=true (member)
View Logs
GET /credentials/POST /credentials/
test should return only credentials shared with me when ?onlySharedWithMe=true (owner)
View Logs
GET /credentials/POST /credentials/
test should return only credentials shared with me when ?onlySharedWithMe=true (owner)
View Logs
GET /credentials/POST /credentials/
test should return only credentials shared with me when ?onlySharedWithMe=true (owner)
View Logs
POST /credentials/GET /credentials should return only relevant creds for member View Logs
POST /credentials/GET /credentials should return only relevant creds for member View Logs
POST /credentials/GET /credentials should return only relevant creds for member View Logs
POST /workflows/GET /
workflows filter should filter by personal project and return only workflows where the
user is owner
View Logs
POST /workflows/GET /
workflows filter should filter by personal project and return only workflows where the
user is owner
View Logs
POST /workflows/GET /
workflows filter should filter by personal project and return only workflows where the
user is owner
View Logs
POST /workflows/GET /
workflows?includeFolders=true should return workflows with scopes and folders when ?inc
ludeScopes=true
View Logs
POST /workflows/GET /
workflows?includeFolders=true should return workflows with scopes and folders when ?inc
ludeScopes=true
View Logs
POST /workflows/GET /
workflows?includeFolders=true should return workflows with scopes and folders when ?inc
ludeScopes=true
View Logs
POST /workflows/GET /
workflows?onlySharedWithMe=true should return only workflows shared with me
View Logs
POST /workflows/GET /
workflows?onlySharedWithMe=true should return only workflows shared with me
View Logs
POST /workflows/GET /
workflows?onlySharedWithMe=true should return only workflows shared with me
View Logs

Fix in Cursor

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.

2 participants