diff --git a/e2e/src/api/specs/library.e2e-spec.ts b/e2e/src/api/specs/library.e2e-spec.ts
index d9ac1eddbe..3e4f971cfd 100644
--- a/e2e/src/api/specs/library.e2e-spec.ts
+++ b/e2e/src/api/specs/library.e2e-spec.ts
@@ -27,7 +27,7 @@ describe('/library', () => {
     await utils.resetDatabase();
     admin = await utils.adminSetup();
     user = await utils.userSetup(admin.accessToken, userDto.user1);
-    library = await utils.createLibrary(admin.accessToken, { type: LibraryType.External });
+    library = await utils.createLibrary(admin.accessToken, { ownerId: admin.userId, type: LibraryType.External });
     websocket = await utils.connectWebsocket(admin.accessToken);
   });
 
@@ -82,7 +82,7 @@ describe('/library', () => {
       const { status, body } = await request(app)
         .post('/library')
         .set('Authorization', `Bearer ${user.accessToken}`)
-        .send({ type: LibraryType.External });
+        .send({ ownerId: admin.userId, type: LibraryType.External });
 
       expect(status).toBe(403);
       expect(body).toEqual(errorDto.forbidden);
@@ -92,7 +92,7 @@ describe('/library', () => {
       const { status, body } = await request(app)
         .post('/library')
         .set('Authorization', `Bearer ${admin.accessToken}`)
-        .send({ type: LibraryType.External });
+        .send({ ownerId: admin.userId, type: LibraryType.External });
 
       expect(status).toBe(201);
       expect(body).toEqual(
@@ -113,6 +113,7 @@ describe('/library', () => {
         .post('/library')
         .set('Authorization', `Bearer ${admin.accessToken}`)
         .send({
+          ownerId: admin.userId,
           type: LibraryType.External,
           name: 'My Awesome Library',
           importPaths: ['/path/to/import'],
@@ -133,6 +134,7 @@ describe('/library', () => {
         .post('/library')
         .set('Authorization', `Bearer ${admin.accessToken}`)
         .send({
+          ownerId: admin.userId,
           type: LibraryType.External,
           name: 'My Awesome Library',
           importPaths: ['/path', '/path'],
@@ -148,6 +150,7 @@ describe('/library', () => {
         .post('/library')
         .set('Authorization', `Bearer ${admin.accessToken}`)
         .send({
+          ownerId: admin.userId,
           type: LibraryType.External,
           name: 'My Awesome Library',
           importPaths: ['/path/to/import'],
@@ -162,7 +165,7 @@ describe('/library', () => {
       const { status, body } = await request(app)
         .post('/library')
         .set('Authorization', `Bearer ${admin.accessToken}`)
-        .send({ type: LibraryType.Upload });
+        .send({ ownerId: admin.userId, type: LibraryType.Upload });
 
       expect(status).toBe(201);
       expect(body).toEqual(
@@ -182,7 +185,7 @@ describe('/library', () => {
       const { status, body } = await request(app)
         .post('/library')
         .set('Authorization', `Bearer ${admin.accessToken}`)
-        .send({ type: LibraryType.Upload, name: 'My Awesome Library' });
+        .send({ ownerId: admin.userId, type: LibraryType.Upload, name: 'My Awesome Library' });
 
       expect(status).toBe(201);
       expect(body).toEqual(
@@ -196,7 +199,7 @@ describe('/library', () => {
       const { status, body } = await request(app)
         .post('/library')
         .set('Authorization', `Bearer ${admin.accessToken}`)
-        .send({ type: LibraryType.Upload, importPaths: ['/path/to/import'] });
+        .send({ ownerId: admin.userId, type: LibraryType.Upload, importPaths: ['/path/to/import'] });
 
       expect(status).toBe(400);
       expect(body).toEqual(errorDto.badRequest('Upload libraries cannot have import paths'));
@@ -206,7 +209,7 @@ describe('/library', () => {
       const { status, body } = await request(app)
         .post('/library')
         .set('Authorization', `Bearer ${admin.accessToken}`)
-        .send({ type: LibraryType.Upload, exclusionPatterns: ['**/Raw/**'] });
+        .send({ ownerId: admin.userId, type: LibraryType.Upload, exclusionPatterns: ['**/Raw/**'] });
 
       expect(status).toBe(400);
       expect(body).toEqual(errorDto.badRequest('Upload libraries cannot have exclusion patterns'));
@@ -330,7 +333,10 @@ describe('/library', () => {
     });
 
     it('should get library by id', async () => {
-      const library = await utils.createLibrary(admin.accessToken, { type: LibraryType.External });
+      const library = await utils.createLibrary(admin.accessToken, {
+        ownerId: admin.userId,
+        type: LibraryType.External,
+      });
 
       const { status, body } = await request(app)
         .get(`/library/${library.id}`)
@@ -386,7 +392,10 @@ describe('/library', () => {
     });
 
     it('should delete an external library', async () => {
-      const library = await utils.createLibrary(admin.accessToken, { type: LibraryType.External });
+      const library = await utils.createLibrary(admin.accessToken, {
+        ownerId: admin.userId,
+        type: LibraryType.External,
+      });
 
       const { status, body } = await request(app)
         .delete(`/library/${library.id}`)
@@ -407,6 +416,7 @@ describe('/library', () => {
 
     it('should delete an external library with assets', async () => {
       const library = await utils.createLibrary(admin.accessToken, {
+        ownerId: admin.userId,
         type: LibraryType.External,
         importPaths: [`${testAssetDirInternal}/temp`],
       });
@@ -455,6 +465,7 @@ describe('/library', () => {
 
     it('should not scan an upload library', async () => {
       const library = await utils.createLibrary(admin.accessToken, {
+        ownerId: admin.userId,
         type: LibraryType.Upload,
       });
 
@@ -468,6 +479,7 @@ describe('/library', () => {
 
     it('should scan external library', async () => {
       const library = await utils.createLibrary(admin.accessToken, {
+        ownerId: admin.userId,
         type: LibraryType.External,
         importPaths: [`${testAssetDirInternal}/temp/directoryA`],
       });
@@ -483,6 +495,7 @@ describe('/library', () => {
 
     it('should scan external library with exclusion pattern', async () => {
       const library = await utils.createLibrary(admin.accessToken, {
+        ownerId: admin.userId,
         type: LibraryType.External,
         importPaths: [`${testAssetDirInternal}/temp`],
         exclusionPatterns: ['**/directoryA'],
@@ -499,6 +512,7 @@ describe('/library', () => {
 
     it('should scan multiple import paths', async () => {
       const library = await utils.createLibrary(admin.accessToken, {
+        ownerId: admin.userId,
         type: LibraryType.External,
         importPaths: [`${testAssetDirInternal}/temp/directoryA`, `${testAssetDirInternal}/temp/directoryB`],
       });
@@ -515,6 +529,7 @@ describe('/library', () => {
 
     it('should pick up new files', async () => {
       const library = await utils.createLibrary(admin.accessToken, {
+        ownerId: admin.userId,
         type: LibraryType.External,
         importPaths: [`${testAssetDirInternal}/temp`],
       });
diff --git a/mobile/openapi/doc/CreateLibraryDto.md b/mobile/openapi/doc/CreateLibraryDto.md
index e0caf1c8a5..94e96493ec 100644
--- a/mobile/openapi/doc/CreateLibraryDto.md
+++ b/mobile/openapi/doc/CreateLibraryDto.md
@@ -13,7 +13,7 @@ Name | Type | Description | Notes
 **isVisible** | **bool** |  | [optional] 
 **isWatched** | **bool** |  | [optional] 
 **name** | **String** |  | [optional] 
-**ownerId** | **String** |  | [optional] 
+**ownerId** | **String** |  | 
 **type** | [**LibraryType**](LibraryType.md) |  | 
 
 [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
diff --git a/mobile/openapi/doc/ValidateLibraryImportPathResponseDto.md b/mobile/openapi/doc/ValidateLibraryImportPathResponseDto.md
index 4601d8d2f2..1ebcb04efd 100644
--- a/mobile/openapi/doc/ValidateLibraryImportPathResponseDto.md
+++ b/mobile/openapi/doc/ValidateLibraryImportPathResponseDto.md
@@ -9,7 +9,7 @@ import 'package:openapi/api.dart';
 Name | Type | Description | Notes
 ------------ | ------------- | ------------- | -------------
 **importPath** | **String** |  | 
-**isValid** | **bool** |  | [optional] [default to false]
+**isValid** | **bool** |  | [default to false]
 **message** | **String** |  | [optional] 
 
 [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
diff --git a/mobile/openapi/lib/model/create_library_dto.dart b/mobile/openapi/lib/model/create_library_dto.dart
index ef656ea2a3..24cc045300 100644
--- a/mobile/openapi/lib/model/create_library_dto.dart
+++ b/mobile/openapi/lib/model/create_library_dto.dart
@@ -18,7 +18,7 @@ class CreateLibraryDto {
     this.isVisible,
     this.isWatched,
     this.name,
-    this.ownerId,
+    required this.ownerId,
     required this.type,
   });
 
@@ -50,13 +50,7 @@ class CreateLibraryDto {
   ///
   String? name;
 
-  ///
-  /// Please note: This property should have been non-nullable! Since the specification file
-  /// does not include a default value (using the "default:" property), however, the generated
-  /// source code must fall back to having a nullable type.
-  /// Consider adding a "default:" property in the specification file to hide this note.
-  ///
-  String? ownerId;
+  String ownerId;
 
   LibraryType type;
 
@@ -78,7 +72,7 @@ class CreateLibraryDto {
     (isVisible == null ? 0 : isVisible!.hashCode) +
     (isWatched == null ? 0 : isWatched!.hashCode) +
     (name == null ? 0 : name!.hashCode) +
-    (ownerId == null ? 0 : ownerId!.hashCode) +
+    (ownerId.hashCode) +
     (type.hashCode);
 
   @override
@@ -103,11 +97,7 @@ class CreateLibraryDto {
     } else {
     //  json[r'name'] = null;
     }
-    if (this.ownerId != null) {
       json[r'ownerId'] = this.ownerId;
-    } else {
-    //  json[r'ownerId'] = null;
-    }
       json[r'type'] = this.type;
     return json;
   }
@@ -129,7 +119,7 @@ class CreateLibraryDto {
         isVisible: mapValueOfType<bool>(json, r'isVisible'),
         isWatched: mapValueOfType<bool>(json, r'isWatched'),
         name: mapValueOfType<String>(json, r'name'),
-        ownerId: mapValueOfType<String>(json, r'ownerId'),
+        ownerId: mapValueOfType<String>(json, r'ownerId')!,
         type: LibraryType.fromJson(json[r'type'])!,
       );
     }
@@ -178,6 +168,7 @@ class CreateLibraryDto {
 
   /// The list of required keys that must be present in a JSON.
   static const requiredKeys = <String>{
+    'ownerId',
     'type',
   };
 }
diff --git a/mobile/openapi/lib/model/validate_library_import_path_response_dto.dart b/mobile/openapi/lib/model/validate_library_import_path_response_dto.dart
index 1297c824c2..142055f2cd 100644
--- a/mobile/openapi/lib/model/validate_library_import_path_response_dto.dart
+++ b/mobile/openapi/lib/model/validate_library_import_path_response_dto.dart
@@ -67,7 +67,7 @@ class ValidateLibraryImportPathResponseDto {
 
       return ValidateLibraryImportPathResponseDto(
         importPath: mapValueOfType<String>(json, r'importPath')!,
-        isValid: mapValueOfType<bool>(json, r'isValid') ?? false,
+        isValid: mapValueOfType<bool>(json, r'isValid')!,
         message: mapValueOfType<String>(json, r'message'),
       );
     }
@@ -117,6 +117,7 @@ class ValidateLibraryImportPathResponseDto {
   /// The list of required keys that must be present in a JSON.
   static const requiredKeys = <String>{
     'importPath',
+    'isValid',
   };
 }
 
diff --git a/open-api/immich-openapi-specs.json b/open-api/immich-openapi-specs.json
index 15ada078cb..82562100a1 100644
--- a/open-api/immich-openapi-specs.json
+++ b/open-api/immich-openapi-specs.json
@@ -7646,6 +7646,7 @@
           }
         },
         "required": [
+          "ownerId",
           "type"
         ],
         "type": "object"
@@ -10689,7 +10690,8 @@
           }
         },
         "required": [
-          "importPath"
+          "importPath",
+          "isValid"
         ],
         "type": "object"
       },
diff --git a/open-api/typescript-sdk/src/fetch-client.ts b/open-api/typescript-sdk/src/fetch-client.ts
index 6a660f4e1b..6b50642520 100644
--- a/open-api/typescript-sdk/src/fetch-client.ts
+++ b/open-api/typescript-sdk/src/fetch-client.ts
@@ -466,7 +466,7 @@ export type CreateLibraryDto = {
     isVisible?: boolean;
     isWatched?: boolean;
     name?: string;
-    ownerId?: string;
+    ownerId: string;
     "type": LibraryType;
 };
 export type UpdateLibraryDto = {
@@ -491,7 +491,7 @@ export type ValidateLibraryDto = {
 };
 export type ValidateLibraryImportPathResponseDto = {
     importPath: string;
-    isValid?: boolean;
+    isValid: boolean;
     message?: string;
 };
 export type ValidateLibraryResponseDto = {
diff --git a/server/e2e/jobs/specs/library-watcher.e2e-spec.ts b/server/e2e/jobs/specs/library-watcher.e2e-spec.ts
index 4757876898..5f05d736bc 100644
--- a/server/e2e/jobs/specs/library-watcher.e2e-spec.ts
+++ b/server/e2e/jobs/specs/library-watcher.e2e-spec.ts
@@ -46,6 +46,7 @@ describe(`Library watcher (e2e)`, () => {
     describe('Single import path', () => {
       beforeEach(async () => {
         await api.libraryApi.create(server, admin.accessToken, {
+          ownerId: admin.userId,
           type: LibraryType.EXTERNAL,
           importPaths: [`${IMMICH_TEST_ASSET_TEMP_PATH}`],
         });
@@ -133,6 +134,7 @@ describe(`Library watcher (e2e)`, () => {
         await fs.mkdir(`${IMMICH_TEST_ASSET_TEMP_PATH}/dir3`, { recursive: true });
 
         await api.libraryApi.create(server, admin.accessToken, {
+          ownerId: admin.userId,
           type: LibraryType.EXTERNAL,
           importPaths: [
             `${IMMICH_TEST_ASSET_TEMP_PATH}/dir1`,
@@ -190,6 +192,7 @@ describe(`Library watcher (e2e)`, () => {
 
     beforeEach(async () => {
       library = await api.libraryApi.create(server, admin.accessToken, {
+        ownerId: admin.userId,
         type: LibraryType.EXTERNAL,
         importPaths: [
           `${IMMICH_TEST_ASSET_TEMP_PATH}/dir1`,
diff --git a/server/e2e/jobs/specs/library.e2e-spec.ts b/server/e2e/jobs/specs/library.e2e-spec.ts
index 4ebb00c4df..a4ee4977a3 100644
--- a/server/e2e/jobs/specs/library.e2e-spec.ts
+++ b/server/e2e/jobs/specs/library.e2e-spec.ts
@@ -1,6 +1,6 @@
-import { LibraryResponseDto, LoginResponseDto } from '@app/domain';
+import { LoginResponseDto } from '@app/domain';
 import { LibraryController } from '@app/immich';
-import { AssetType, LibraryType } from '@app/infra/entities';
+import { LibraryType } from '@app/infra/entities';
 import { errorStub, uuidStub } from '@test/fixtures';
 import * as fs from 'node:fs';
 import request from 'supertest';
@@ -41,6 +41,7 @@ describe(`${LibraryController.name} (e2e)`, () => {
       });
 
       const library = await api.libraryApi.create(server, admin.accessToken, {
+        ownerId: admin.userId,
         type: LibraryType.EXTERNAL,
         importPaths: [`${IMMICH_TEST_ASSET_TEMP_PATH}`],
       });
@@ -72,6 +73,7 @@ describe(`${LibraryController.name} (e2e)`, () => {
 
     it('should scan new files', async () => {
       const library = await api.libraryApi.create(server, admin.accessToken, {
+        ownerId: admin.userId,
         type: LibraryType.EXTERNAL,
         importPaths: [`${IMMICH_TEST_ASSET_TEMP_PATH}`],
       });
@@ -107,6 +109,7 @@ describe(`${LibraryController.name} (e2e)`, () => {
     describe('with refreshModifiedFiles=true', () => {
       it('should reimport modified files', async () => {
         const library = await api.libraryApi.create(server, admin.accessToken, {
+          ownerId: admin.userId,
           type: LibraryType.EXTERNAL,
           importPaths: [`${IMMICH_TEST_ASSET_TEMP_PATH}`],
         });
@@ -153,6 +156,7 @@ describe(`${LibraryController.name} (e2e)`, () => {
 
       it('should not reimport unmodified files', async () => {
         const library = await api.libraryApi.create(server, admin.accessToken, {
+          ownerId: admin.userId,
           type: LibraryType.EXTERNAL,
           importPaths: [`${IMMICH_TEST_ASSET_TEMP_PATH}`],
         });
@@ -192,6 +196,7 @@ describe(`${LibraryController.name} (e2e)`, () => {
     describe('with refreshAllFiles=true', () => {
       it('should reimport all files', async () => {
         const library = await api.libraryApi.create(server, admin.accessToken, {
+          ownerId: admin.userId,
           type: LibraryType.EXTERNAL,
           importPaths: [`${IMMICH_TEST_ASSET_TEMP_PATH}`],
         });
@@ -251,6 +256,7 @@ describe(`${LibraryController.name} (e2e)`, () => {
       });
 
       const library = await api.libraryApi.create(server, admin.accessToken, {
+        ownerId: admin.userId,
         type: LibraryType.EXTERNAL,
         importPaths: [`${IMMICH_TEST_ASSET_TEMP_PATH}`],
       });
@@ -277,6 +283,7 @@ describe(`${LibraryController.name} (e2e)`, () => {
 
     it('should not remove online files', async () => {
       const library = await api.libraryApi.create(server, admin.accessToken, {
+        ownerId: admin.userId,
         type: LibraryType.EXTERNAL,
         importPaths: [`${IMMICH_TEST_ASSET_PATH}/albums/nature`],
       });
diff --git a/server/package.json b/server/package.json
index c575571d07..d60f67a1f8 100644
--- a/server/package.json
+++ b/server/package.json
@@ -153,7 +153,7 @@
     "coverageDirectory": "./coverage",
     "coverageThreshold": {
       "./src/domain/": {
-        "branches": 79,
+        "branches": 75,
         "functions": 80,
         "lines": 90,
         "statements": 90
diff --git a/server/src/domain/access/access.core.ts b/server/src/domain/access/access.core.ts
index 7063cb49a2..40b01de1da 100644
--- a/server/src/domain/access/access.core.ts
+++ b/server/src/domain/access/access.core.ts
@@ -33,12 +33,6 @@ export enum Permission {
   TIMELINE_READ = 'timeline.read',
   TIMELINE_DOWNLOAD = 'timeline.download',
 
-  LIBRARY_CREATE = 'library.create',
-  LIBRARY_READ = 'library.read',
-  LIBRARY_UPDATE = 'library.update',
-  LIBRARY_DELETE = 'library.delete',
-  LIBRARY_DOWNLOAD = 'library.download',
-
   PERSON_READ = 'person.read',
   PERSON_WRITE = 'person.write',
   PERSON_MERGE = 'person.merge',
@@ -261,29 +255,6 @@ export class AccessCore {
         return ids.has(auth.user.id) ? new Set([auth.user.id]) : new Set();
       }
 
-      case Permission.LIBRARY_READ: {
-        if (auth.user.isAdmin) {
-          return new Set(ids);
-        }
-        const isOwner = await this.repository.library.checkOwnerAccess(auth.user.id, ids);
-        const isPartner = await this.repository.library.checkPartnerAccess(auth.user.id, setDifference(ids, isOwner));
-        return setUnion(isOwner, isPartner);
-      }
-
-      case Permission.LIBRARY_UPDATE: {
-        if (auth.user.isAdmin) {
-          return new Set(ids);
-        }
-        return await this.repository.library.checkOwnerAccess(auth.user.id, ids);
-      }
-
-      case Permission.LIBRARY_DELETE: {
-        if (auth.user.isAdmin) {
-          return new Set(ids);
-        }
-        return await this.repository.library.checkOwnerAccess(auth.user.id, ids);
-      }
-
       case Permission.PERSON_READ: {
         return await this.repository.person.checkOwnerAccess(auth.user.id, ids);
       }
diff --git a/server/src/domain/library/library.dto.ts b/server/src/domain/library/library.dto.ts
index 5e4bb4ec6b..fcce02f878 100644
--- a/server/src/domain/library/library.dto.ts
+++ b/server/src/domain/library/library.dto.ts
@@ -8,8 +8,8 @@ export class CreateLibraryDto {
   @ApiProperty({ enumName: 'LibraryType', enum: LibraryType })
   type!: LibraryType;
 
-  @ValidateUUID({ optional: true })
-  ownerId?: string;
+  @ValidateUUID()
+  ownerId!: string;
 
   @IsString()
   @Optional()
diff --git a/server/src/domain/library/library.service.spec.ts b/server/src/domain/library/library.service.spec.ts
index 57bdf7373d..3b5258b975 100644
--- a/server/src/domain/library/library.service.spec.ts
+++ b/server/src/domain/library/library.service.spec.ts
@@ -706,7 +706,7 @@ describe(LibraryService.name, () => {
       libraryMock.getUploadLibraryCount.mockResolvedValue(2);
       libraryMock.get.mockResolvedValue(libraryStub.externalLibrary1);
 
-      await sut.delete(authStub.admin, libraryStub.externalLibrary1.id);
+      await sut.delete(libraryStub.externalLibrary1.id);
 
       expect(jobMock.queue).toHaveBeenCalledWith({
         name: JobName.LIBRARY_DELETE,
@@ -721,9 +721,7 @@ describe(LibraryService.name, () => {
       libraryMock.getUploadLibraryCount.mockResolvedValue(1);
       libraryMock.get.mockResolvedValue(libraryStub.uploadLibrary1);
 
-      await expect(sut.delete(authStub.admin, libraryStub.uploadLibrary1.id)).rejects.toBeInstanceOf(
-        BadRequestException,
-      );
+      await expect(sut.delete(libraryStub.uploadLibrary1.id)).rejects.toBeInstanceOf(BadRequestException);
 
       expect(jobMock.queue).not.toHaveBeenCalled();
       expect(jobMock.queueAll).not.toHaveBeenCalled();
@@ -735,7 +733,7 @@ describe(LibraryService.name, () => {
       libraryMock.getUploadLibraryCount.mockResolvedValue(1);
       libraryMock.get.mockResolvedValue(libraryStub.externalLibrary1);
 
-      await sut.delete(authStub.admin, libraryStub.externalLibrary1.id);
+      await sut.delete(libraryStub.externalLibrary1.id);
 
       expect(jobMock.queue).toHaveBeenCalledWith({
         name: JobName.LIBRARY_DELETE,
@@ -757,26 +755,16 @@ describe(LibraryService.name, () => {
       storageMock.watch.mockImplementation(makeMockWatcher({ close: mockClose }));
 
       await sut.init();
-      await sut.delete(authStub.admin, libraryStub.externalLibraryWithImportPaths1.id);
+      await sut.delete(libraryStub.externalLibraryWithImportPaths1.id);
 
       expect(mockClose).toHaveBeenCalled();
     });
   });
 
-  describe('getCount', () => {
-    it('should call the repository', async () => {
-      libraryMock.getCountForUser.mockResolvedValue(17);
-
-      await expect(sut.getCount(authStub.admin)).resolves.toBe(17);
-
-      expect(libraryMock.getCountForUser).toHaveBeenCalledWith(authStub.admin.user.id);
-    });
-  });
-
   describe('get', () => {
     it('should return a library', async () => {
       libraryMock.get.mockResolvedValue(libraryStub.uploadLibrary1);
-      await expect(sut.get(authStub.admin, libraryStub.uploadLibrary1.id)).resolves.toEqual(
+      await expect(sut.get(libraryStub.uploadLibrary1.id)).resolves.toEqual(
         expect.objectContaining({
           id: libraryStub.uploadLibrary1.id,
           name: libraryStub.uploadLibrary1.name,
@@ -789,15 +777,16 @@ describe(LibraryService.name, () => {
 
     it('should throw an error when a library is not found', async () => {
       libraryMock.get.mockResolvedValue(null);
-      await expect(sut.get(authStub.admin, libraryStub.uploadLibrary1.id)).rejects.toBeInstanceOf(BadRequestException);
+      await expect(sut.get(libraryStub.uploadLibrary1.id)).rejects.toBeInstanceOf(BadRequestException);
       expect(libraryMock.get).toHaveBeenCalledWith(libraryStub.uploadLibrary1.id);
     });
   });
 
   describe('getStatistics', () => {
     it('should return library statistics', async () => {
+      libraryMock.get.mockResolvedValue(libraryStub.uploadLibrary1);
       libraryMock.getStatistics.mockResolvedValue({ photos: 10, videos: 0, total: 10, usage: 1337 });
-      await expect(sut.getStatistics(authStub.admin, libraryStub.uploadLibrary1.id)).resolves.toEqual({
+      await expect(sut.getStatistics(libraryStub.uploadLibrary1.id)).resolves.toEqual({
         photos: 10,
         videos: 0,
         total: 10,
@@ -812,11 +801,7 @@ describe(LibraryService.name, () => {
     describe('external library', () => {
       it('should create with default settings', async () => {
         libraryMock.create.mockResolvedValue(libraryStub.externalLibrary1);
-        await expect(
-          sut.create(authStub.admin, {
-            type: LibraryType.EXTERNAL,
-          }),
-        ).resolves.toEqual(
+        await expect(sut.create({ ownerId: authStub.admin.user.id, type: LibraryType.EXTERNAL })).resolves.toEqual(
           expect.objectContaining({
             id: libraryStub.externalLibrary1.id,
             type: LibraryType.EXTERNAL,
@@ -845,10 +830,7 @@ describe(LibraryService.name, () => {
       it('should create with name', async () => {
         libraryMock.create.mockResolvedValue(libraryStub.externalLibrary1);
         await expect(
-          sut.create(authStub.admin, {
-            type: LibraryType.EXTERNAL,
-            name: 'My Awesome Library',
-          }),
+          sut.create({ ownerId: authStub.admin.user.id, type: LibraryType.EXTERNAL, name: 'My Awesome Library' }),
         ).resolves.toEqual(
           expect.objectContaining({
             id: libraryStub.externalLibrary1.id,
@@ -878,10 +860,7 @@ describe(LibraryService.name, () => {
       it('should create invisible', async () => {
         libraryMock.create.mockResolvedValue(libraryStub.externalLibrary1);
         await expect(
-          sut.create(authStub.admin, {
-            type: LibraryType.EXTERNAL,
-            isVisible: false,
-          }),
+          sut.create({ ownerId: authStub.admin.user.id, type: LibraryType.EXTERNAL, isVisible: false }),
         ).resolves.toEqual(
           expect.objectContaining({
             id: libraryStub.externalLibrary1.id,
@@ -911,7 +890,8 @@ describe(LibraryService.name, () => {
       it('should create with import paths', async () => {
         libraryMock.create.mockResolvedValue(libraryStub.externalLibrary1);
         await expect(
-          sut.create(authStub.admin, {
+          sut.create({
+            ownerId: authStub.admin.user.id,
             type: LibraryType.EXTERNAL,
             importPaths: ['/data/images', '/data/videos'],
           }),
@@ -948,7 +928,8 @@ describe(LibraryService.name, () => {
         libraryMock.getAll.mockResolvedValue([]);
 
         await sut.init();
-        await sut.create(authStub.admin, {
+        await sut.create({
+          ownerId: authStub.admin.user.id,
           type: LibraryType.EXTERNAL,
           importPaths: libraryStub.externalLibraryWithImportPaths1.importPaths,
         });
@@ -963,7 +944,8 @@ describe(LibraryService.name, () => {
       it('should create with exclusion patterns', async () => {
         libraryMock.create.mockResolvedValue(libraryStub.externalLibrary1);
         await expect(
-          sut.create(authStub.admin, {
+          sut.create({
+            ownerId: authStub.admin.user.id,
             type: LibraryType.EXTERNAL,
             exclusionPatterns: ['*.tmp', '*.bak'],
           }),
@@ -997,11 +979,7 @@ describe(LibraryService.name, () => {
     describe('upload library', () => {
       it('should create with default settings', async () => {
         libraryMock.create.mockResolvedValue(libraryStub.uploadLibrary1);
-        await expect(
-          sut.create(authStub.admin, {
-            type: LibraryType.UPLOAD,
-          }),
-        ).resolves.toEqual(
+        await expect(sut.create({ ownerId: authStub.admin.user.id, type: LibraryType.UPLOAD })).resolves.toEqual(
           expect.objectContaining({
             id: libraryStub.uploadLibrary1.id,
             type: LibraryType.UPLOAD,
@@ -1030,10 +1008,7 @@ describe(LibraryService.name, () => {
       it('should create with name', async () => {
         libraryMock.create.mockResolvedValue(libraryStub.uploadLibrary1);
         await expect(
-          sut.create(authStub.admin, {
-            type: LibraryType.UPLOAD,
-            name: 'My Awesome Library',
-          }),
+          sut.create({ ownerId: authStub.admin.user.id, type: LibraryType.UPLOAD, name: 'My Awesome Library' }),
         ).resolves.toEqual(
           expect.objectContaining({
             id: libraryStub.uploadLibrary1.id,
@@ -1062,7 +1037,8 @@ describe(LibraryService.name, () => {
 
       it('should not create with import paths', async () => {
         await expect(
-          sut.create(authStub.admin, {
+          sut.create({
+            ownerId: authStub.admin.user.id,
             type: LibraryType.UPLOAD,
             importPaths: ['/data/images', '/data/videos'],
           }),
@@ -1073,7 +1049,8 @@ describe(LibraryService.name, () => {
 
       it('should not create with exclusion patterns', async () => {
         await expect(
-          sut.create(authStub.admin, {
+          sut.create({
+            ownerId: authStub.admin.user.id,
             type: LibraryType.UPLOAD,
             exclusionPatterns: ['*.tmp', '*.bak'],
           }),
@@ -1084,10 +1061,7 @@ describe(LibraryService.name, () => {
 
       it('should not create watched', async () => {
         await expect(
-          sut.create(authStub.admin, {
-            type: LibraryType.UPLOAD,
-            isWatched: true,
-          }),
+          sut.create({ ownerId: authStub.admin.user.id, type: LibraryType.UPLOAD, isWatched: true }),
         ).rejects.toBeInstanceOf(BadRequestException);
 
         expect(storageMock.watch).not.toHaveBeenCalled();
@@ -1117,14 +1091,9 @@ describe(LibraryService.name, () => {
 
     it('should update library', async () => {
       libraryMock.update.mockResolvedValue(libraryStub.uploadLibrary1);
-      await expect(sut.update(authStub.admin, authStub.admin.user.id, {})).resolves.toEqual(
-        mapLibrary(libraryStub.uploadLibrary1),
-      );
-      expect(libraryMock.update).toHaveBeenCalledWith(
-        expect.objectContaining({
-          id: authStub.admin.user.id,
-        }),
-      );
+      libraryMock.get.mockResolvedValue(libraryStub.uploadLibrary1);
+      await expect(sut.update('library-id', {})).resolves.toEqual(mapLibrary(libraryStub.uploadLibrary1));
+      expect(libraryMock.update).toHaveBeenCalledWith(expect.objectContaining({ id: 'library-id' }));
     });
 
     it('should re-watch library when updating import paths', async () => {
@@ -1137,15 +1106,11 @@ describe(LibraryService.name, () => {
 
       storageMock.checkFileExists.mockResolvedValue(true);
 
-      await expect(
-        sut.update(authStub.admin, authStub.admin.user.id, { importPaths: ['/data/user1/foo'] }),
-      ).resolves.toEqual(mapLibrary(libraryStub.externalLibraryWithImportPaths1));
-
-      expect(libraryMock.update).toHaveBeenCalledWith(
-        expect.objectContaining({
-          id: authStub.admin.user.id,
-        }),
+      await expect(sut.update('library-id', { importPaths: ['/data/user1/foo'] })).resolves.toEqual(
+        mapLibrary(libraryStub.externalLibraryWithImportPaths1),
       );
+
+      expect(libraryMock.update).toHaveBeenCalledWith(expect.objectContaining({ id: 'library-id' }));
       expect(storageMock.watch).toHaveBeenCalledWith(
         libraryStub.externalLibraryWithImportPaths1.importPaths,
         expect.anything(),
@@ -1158,15 +1123,11 @@ describe(LibraryService.name, () => {
       configMock.load.mockResolvedValue(systemConfigStub.libraryWatchEnabled);
       libraryMock.get.mockResolvedValue(libraryStub.externalLibraryWithImportPaths1);
 
-      await expect(sut.update(authStub.admin, authStub.admin.user.id, { exclusionPatterns: ['bar'] })).resolves.toEqual(
+      await expect(sut.update('library-id', { exclusionPatterns: ['bar'] })).resolves.toEqual(
         mapLibrary(libraryStub.externalLibraryWithImportPaths1),
       );
 
-      expect(libraryMock.update).toHaveBeenCalledWith(
-        expect.objectContaining({
-          id: authStub.admin.user.id,
-        }),
-      );
+      expect(libraryMock.update).toHaveBeenCalledWith(expect.objectContaining({ id: 'library-id' }));
       expect(storageMock.watch).toHaveBeenCalledWith(
         expect.arrayContaining([expect.any(String)]),
         expect.anything(),
@@ -1411,7 +1372,7 @@ describe(LibraryService.name, () => {
     it('should queue a library scan of external library', async () => {
       libraryMock.get.mockResolvedValue(libraryStub.externalLibrary1);
 
-      await sut.queueScan(authStub.admin, libraryStub.externalLibrary1.id, {});
+      await sut.queueScan(libraryStub.externalLibrary1.id, {});
 
       expect(jobMock.queue.mock.calls).toEqual([
         [
@@ -1430,9 +1391,7 @@ describe(LibraryService.name, () => {
     it('should not queue a library scan of upload library', async () => {
       libraryMock.get.mockResolvedValue(libraryStub.uploadLibrary1);
 
-      await expect(sut.queueScan(authStub.admin, libraryStub.uploadLibrary1.id, {})).rejects.toBeInstanceOf(
-        BadRequestException,
-      );
+      await expect(sut.queueScan(libraryStub.uploadLibrary1.id, {})).rejects.toBeInstanceOf(BadRequestException);
 
       expect(jobMock.queue).not.toBeCalled();
     });
@@ -1440,7 +1399,7 @@ describe(LibraryService.name, () => {
     it('should queue a library scan of all modified assets', async () => {
       libraryMock.get.mockResolvedValue(libraryStub.externalLibrary1);
 
-      await sut.queueScan(authStub.admin, libraryStub.externalLibrary1.id, { refreshModifiedFiles: true });
+      await sut.queueScan(libraryStub.externalLibrary1.id, { refreshModifiedFiles: true });
 
       expect(jobMock.queue.mock.calls).toEqual([
         [
@@ -1459,7 +1418,7 @@ describe(LibraryService.name, () => {
     it('should queue a forced library scan', async () => {
       libraryMock.get.mockResolvedValue(libraryStub.externalLibrary1);
 
-      await sut.queueScan(authStub.admin, libraryStub.externalLibrary1.id, { refreshAllFiles: true });
+      await sut.queueScan(libraryStub.externalLibrary1.id, { refreshAllFiles: true });
 
       expect(jobMock.queue.mock.calls).toEqual([
         [
@@ -1478,7 +1437,7 @@ describe(LibraryService.name, () => {
 
   describe('queueEmptyTrash', () => {
     it('should queue the trash job', async () => {
-      await sut.queueRemoveOffline(authStub.admin, libraryStub.externalLibrary1.id);
+      await sut.queueRemoveOffline(libraryStub.externalLibrary1.id);
 
       expect(jobMock.queue.mock.calls).toEqual([
         [
@@ -1566,17 +1525,15 @@ describe(LibraryService.name, () => {
 
       storageMock.checkFileExists.mockResolvedValue(true);
 
-      const result = await sut.validate(authStub.external1, libraryStub.externalLibraryWithImportPaths1.id, {
-        importPaths: ['/data/user1/'],
+      await expect(sut.validate('library-id', { importPaths: ['/data/user1/'] })).resolves.toEqual({
+        importPaths: [
+          {
+            importPath: '/data/user1/',
+            isValid: true,
+            message: undefined,
+          },
+        ],
       });
-
-      expect(result.importPaths).toEqual([
-        {
-          importPath: '/data/user1/',
-          isValid: true,
-          message: undefined,
-        },
-      ]);
     });
 
     it('should detect when path does not exist', async () => {
@@ -1585,17 +1542,15 @@ describe(LibraryService.name, () => {
         throw error;
       });
 
-      const result = await sut.validate(authStub.external1, libraryStub.externalLibraryWithImportPaths1.id, {
-        importPaths: ['/data/user1/'],
+      await expect(sut.validate('library-id', { importPaths: ['/data/user1/'] })).resolves.toEqual({
+        importPaths: [
+          {
+            importPath: '/data/user1/',
+            isValid: false,
+            message: 'Path does not exist (ENOENT)',
+          },
+        ],
       });
-
-      expect(result.importPaths).toEqual([
-        {
-          importPath: '/data/user1/',
-          isValid: false,
-          message: 'Path does not exist (ENOENT)',
-        },
-      ]);
     });
 
     it('should detect when path is not a directory', async () => {
@@ -1603,17 +1558,15 @@ describe(LibraryService.name, () => {
         isDirectory: () => false,
       } as Stats);
 
-      const result = await sut.validate(authStub.external1, libraryStub.externalLibraryWithImportPaths1.id, {
-        importPaths: ['/data/user1/file'],
+      await expect(sut.validate('library-id', { importPaths: ['/data/user1/file'] })).resolves.toEqual({
+        importPaths: [
+          {
+            importPath: '/data/user1/file',
+            isValid: false,
+            message: 'Not a directory',
+          },
+        ],
       });
-
-      expect(result.importPaths).toEqual([
-        {
-          importPath: '/data/user1/file',
-          isValid: false,
-          message: 'Not a directory',
-        },
-      ]);
     });
 
     it('should return an unknown exception from stat', async () => {
@@ -1621,17 +1574,15 @@ describe(LibraryService.name, () => {
         throw new Error('Unknown error');
       });
 
-      const result = await sut.validate(authStub.external1, libraryStub.externalLibraryWithImportPaths1.id, {
-        importPaths: ['/data/user1/'],
+      await expect(sut.validate('library-id', { importPaths: ['/data/user1/'] })).resolves.toEqual({
+        importPaths: [
+          {
+            importPath: '/data/user1/',
+            isValid: false,
+            message: 'Error: Unknown error',
+          },
+        ],
       });
-
-      expect(result.importPaths).toEqual([
-        {
-          importPath: '/data/user1/',
-          isValid: false,
-          message: 'Error: Unknown error',
-        },
-      ]);
     });
 
     it('should detect when access rights are missing', async () => {
@@ -1641,17 +1592,15 @@ describe(LibraryService.name, () => {
 
       storageMock.checkFileExists.mockResolvedValue(false);
 
-      const result = await sut.validate(authStub.external1, libraryStub.externalLibraryWithImportPaths1.id, {
-        importPaths: ['/data/user1/'],
+      await expect(sut.validate('library-id', { importPaths: ['/data/user1/'] })).resolves.toEqual({
+        importPaths: [
+          {
+            importPath: '/data/user1/',
+            isValid: false,
+            message: 'Lacking read permission for folder',
+          },
+        ],
       });
-
-      expect(result.importPaths).toEqual([
-        {
-          importPath: '/data/user1/',
-          isValid: false,
-          message: 'Lacking read permission for folder',
-        },
-      ]);
     });
 
     it('should detect when import path is in immich media folder', async () => {
@@ -1659,26 +1608,26 @@ describe(LibraryService.name, () => {
       const validImport = libraryStub.hasImmichPaths.importPaths[1];
       when(storageMock.checkFileExists).calledWith(validImport, R_OK).mockResolvedValue(true);
 
-      const result = await sut.validate(authStub.external1, libraryStub.hasImmichPaths.id, {
-        importPaths: libraryStub.hasImmichPaths.importPaths,
+      await expect(
+        sut.validate('library-id', { importPaths: libraryStub.hasImmichPaths.importPaths }),
+      ).resolves.toEqual({
+        importPaths: [
+          {
+            importPath: libraryStub.hasImmichPaths.importPaths[0],
+            isValid: false,
+            message: 'Cannot use media upload folder for external libraries',
+          },
+          {
+            importPath: validImport,
+            isValid: true,
+          },
+          {
+            importPath: libraryStub.hasImmichPaths.importPaths[2],
+            isValid: false,
+            message: 'Cannot use media upload folder for external libraries',
+          },
+        ],
       });
-
-      expect(result.importPaths).toEqual([
-        {
-          importPath: libraryStub.hasImmichPaths.importPaths[0],
-          isValid: false,
-          message: 'Cannot use media upload folder for external libraries',
-        },
-        {
-          importPath: validImport,
-          isValid: true,
-        },
-        {
-          importPath: libraryStub.hasImmichPaths.importPaths[2],
-          isValid: false,
-          message: 'Cannot use media upload folder for external libraries',
-        },
-      ]);
     });
   });
 });
diff --git a/server/src/domain/library/library.service.ts b/server/src/domain/library/library.service.ts
index 12d135fa30..000acac29d 100644
--- a/server/src/domain/library/library.service.ts
+++ b/server/src/domain/library/library.service.ts
@@ -8,8 +8,7 @@ import { EventEmitter } from 'node:events';
 import { Stats } from 'node:fs';
 import path, { basename, parse } from 'node:path';
 import picomatch from 'picomatch';
-import { AccessCore, Permission } from '../access';
-import { AuthDto } from '../auth';
+import { AccessCore } from '../access';
 import { mimeTypes } from '../domain.constant';
 import { handlePromiseError, usePagination, validateCronExpression } from '../domain.util';
 import { IBaseJob, IEntityJob, ILibraryFileJob, ILibraryRefreshJob, JOBS_ASSET_PAGINATION_SIZE, JobName } from '../job';
@@ -226,24 +225,17 @@ export class LibraryService extends EventEmitter {
     }
   }
 
-  async getStatistics(auth: AuthDto, id: string): Promise<LibraryStatsResponseDto> {
-    await this.access.requirePermission(auth, Permission.LIBRARY_READ, id);
-
+  async getStatistics(id: string): Promise<LibraryStatsResponseDto> {
+    await this.findOrFail(id);
     return this.repository.getStatistics(id);
   }
 
-  async getCount(auth: AuthDto): Promise<number> {
-    return this.repository.getCountForUser(auth.user.id);
-  }
-
-  async get(auth: AuthDto, id: string): Promise<LibraryResponseDto> {
-    await this.access.requirePermission(auth, Permission.LIBRARY_READ, id);
-
+  async get(id: string): Promise<LibraryResponseDto> {
     const library = await this.findOrFail(id);
     return mapLibrary(library);
   }
 
-  async getAll(auth: AuthDto, dto: SearchLibraryDto): Promise<LibraryResponseDto[]> {
+  async getAll(dto: SearchLibraryDto): Promise<LibraryResponseDto[]> {
     const libraries = await this.repository.getAll(false, dto.type);
     return libraries.map((library) => mapLibrary(library));
   }
@@ -257,7 +249,7 @@ export class LibraryService extends EventEmitter {
     return JobStatus.SUCCESS;
   }
 
-  async create(auth: AuthDto, dto: CreateLibraryDto): Promise<LibraryResponseDto> {
+  async create(dto: CreateLibraryDto): Promise<LibraryResponseDto> {
     switch (dto.type) {
       case LibraryType.EXTERNAL: {
         if (!dto.name) {
@@ -282,14 +274,8 @@ export class LibraryService extends EventEmitter {
       }
     }
 
-    let ownerId = auth.user.id;
-
-    if (dto.ownerId) {
-      ownerId = dto.ownerId;
-    }
-
     const library = await this.repository.create({
-      ownerId,
+      ownerId: dto.ownerId,
       name: dto.name,
       type: dto.type,
       importPaths: dto.importPaths ?? [],
@@ -297,7 +283,7 @@ export class LibraryService extends EventEmitter {
       isVisible: dto.isVisible ?? true,
     });
 
-    this.logger.log(`Creating ${dto.type} library for user ${auth.user.name}`);
+    this.logger.log(`Creating ${dto.type} library for ${dto.ownerId}}`);
 
     if (dto.type === LibraryType.EXTERNAL) {
       await this.watch(library.id);
@@ -364,29 +350,19 @@ export class LibraryService extends EventEmitter {
     return validation;
   }
 
-  public async validate(auth: AuthDto, id: string, dto: ValidateLibraryDto): Promise<ValidateLibraryResponseDto> {
-    await this.access.requirePermission(auth, Permission.LIBRARY_UPDATE, id);
-
-    const response = new ValidateLibraryResponseDto();
-
-    if (dto.importPaths) {
-      response.importPaths = await Promise.all(
-        dto.importPaths.map(async (importPath) => {
-          return await this.validateImportPath(importPath);
-        }),
-      );
-    }
-
-    return response;
+  async validate(id: string, dto: ValidateLibraryDto): Promise<ValidateLibraryResponseDto> {
+    const importPaths = await Promise.all(
+      (dto.importPaths || []).map((importPath) => this.validateImportPath(importPath)),
+    );
+    return { importPaths };
   }
 
-  async update(auth: AuthDto, id: string, dto: UpdateLibraryDto): Promise<LibraryResponseDto> {
-    await this.access.requirePermission(auth, Permission.LIBRARY_UPDATE, id);
-
+  async update(id: string, dto: UpdateLibraryDto): Promise<LibraryResponseDto> {
+    await this.findOrFail(id);
     const library = await this.repository.update({ id, ...dto });
 
     if (dto.importPaths) {
-      const validation = await this.validate(auth, id, { importPaths: dto.importPaths });
+      const validation = await this.validate(id, { importPaths: dto.importPaths });
       if (validation.importPaths) {
         for (const path of validation.importPaths) {
           if (!path.isValid) {
@@ -404,11 +380,9 @@ export class LibraryService extends EventEmitter {
     return mapLibrary(library);
   }
 
-  async delete(auth: AuthDto, id: string) {
-    await this.access.requirePermission(auth, Permission.LIBRARY_DELETE, id);
-
+  async delete(id: string) {
     const library = await this.findOrFail(id);
-    const uploadCount = await this.repository.getUploadLibraryCount(auth.user.id);
+    const uploadCount = await this.repository.getUploadLibraryCount(library.ownerId);
     if (library.type === LibraryType.UPLOAD && uploadCount <= 1) {
       throw new BadRequestException('Cannot delete the last upload library');
     }
@@ -565,11 +539,9 @@ export class LibraryService extends EventEmitter {
     return JobStatus.SUCCESS;
   }
 
-  async queueScan(auth: AuthDto, id: string, dto: ScanLibraryDto) {
-    await this.access.requirePermission(auth, Permission.LIBRARY_UPDATE, id);
-
-    const library = await this.repository.get(id);
-    if (!library || library.type !== LibraryType.EXTERNAL) {
+  async queueScan(id: string, dto: ScanLibraryDto) {
+    const library = await this.findOrFail(id);
+    if (library.type !== LibraryType.EXTERNAL) {
       throw new BadRequestException('Can only refresh external libraries');
     }
 
@@ -583,16 +555,9 @@ export class LibraryService extends EventEmitter {
     });
   }
 
-  async queueRemoveOffline(auth: AuthDto, id: string) {
+  async queueRemoveOffline(id: string) {
     this.logger.verbose(`Removing offline files from library: ${id}`);
-    await this.access.requirePermission(auth, Permission.LIBRARY_UPDATE, id);
-
-    await this.jobRepository.queue({
-      name: JobName.LIBRARY_REMOVE_OFFLINE,
-      data: {
-        id,
-      },
-    });
+    await this.jobRepository.queue({ name: JobName.LIBRARY_REMOVE_OFFLINE, data: { id } });
   }
 
   async handleQueueAllScan(job: IBaseJob): Promise<JobStatus> {
diff --git a/server/src/domain/repositories/access.repository.ts b/server/src/domain/repositories/access.repository.ts
index 6aa70a2123..7924a29dd3 100644
--- a/server/src/domain/repositories/access.repository.ts
+++ b/server/src/domain/repositories/access.repository.ts
@@ -26,7 +26,6 @@ export interface IAccessRepository {
 
   library: {
     checkOwnerAccess(userId: string, libraryIds: Set<string>): Promise<Set<string>>;
-    checkPartnerAccess(userId: string, partnerIds: Set<string>): Promise<Set<string>>;
   };
 
   timeline: {
diff --git a/server/src/immich/controllers/library.controller.ts b/server/src/immich/controllers/library.controller.ts
index 801dc173d9..2b509645c3 100644
--- a/server/src/immich/controllers/library.controller.ts
+++ b/server/src/immich/controllers/library.controller.ts
@@ -1,5 +1,4 @@
 import {
-  AuthDto,
   CreateLibraryDto as CreateDto,
   LibraryService,
   LibraryStatsResponseDto,
@@ -12,7 +11,7 @@ import {
 } from '@app/domain';
 import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Put, Query } from '@nestjs/common';
 import { ApiTags } from '@nestjs/swagger';
-import { AdminRoute, Auth, Authenticated } from '../app.guard';
+import { AdminRoute, Authenticated } from '../app.guard';
 import { UUIDParamDto } from './dto/uuid-param.dto';
 
 @ApiTags('Library')
@@ -23,55 +22,52 @@ export class LibraryController {
   constructor(private service: LibraryService) {}
 
   @Get()
-  getAllLibraries(@Auth() auth: AuthDto, @Query() dto: SearchLibraryDto): Promise<ResponseDto[]> {
-    return this.service.getAll(auth, dto);
+  getAllLibraries(@Query() dto: SearchLibraryDto): Promise<ResponseDto[]> {
+    return this.service.getAll(dto);
   }
 
   @Post()
-  createLibrary(@Auth() auth: AuthDto, @Body() dto: CreateDto): Promise<ResponseDto> {
-    return this.service.create(auth, dto);
+  createLibrary(@Body() dto: CreateDto): Promise<ResponseDto> {
+    return this.service.create(dto);
   }
 
   @Put(':id')
-  updateLibrary(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto, @Body() dto: UpdateDto): Promise<ResponseDto> {
-    return this.service.update(auth, id, dto);
+  updateLibrary(@Param() { id }: UUIDParamDto, @Body() dto: UpdateDto): Promise<ResponseDto> {
+    return this.service.update(id, dto);
   }
 
   @Get(':id')
-  getLibrary(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<ResponseDto> {
-    return this.service.get(auth, id);
+  getLibrary(@Param() { id }: UUIDParamDto): Promise<ResponseDto> {
+    return this.service.get(id);
   }
 
   @Post(':id/validate')
   @HttpCode(200)
-  validate(
-    @Auth() auth: AuthDto,
-    @Param() { id }: UUIDParamDto,
-    @Body() dto: ValidateLibraryDto,
-  ): Promise<ValidateLibraryResponseDto> {
-    return this.service.validate(auth, id, dto);
+  // TODO: change endpoint to validate current settings instead
+  validate(@Param() { id }: UUIDParamDto, @Body() dto: ValidateLibraryDto): Promise<ValidateLibraryResponseDto> {
+    return this.service.validate(id, dto);
   }
 
   @Delete(':id')
   @HttpCode(HttpStatus.NO_CONTENT)
-  deleteLibrary(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<void> {
-    return this.service.delete(auth, id);
+  deleteLibrary(@Param() { id }: UUIDParamDto): Promise<void> {
+    return this.service.delete(id);
   }
 
   @Get(':id/statistics')
-  getLibraryStatistics(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<LibraryStatsResponseDto> {
-    return this.service.getStatistics(auth, id);
+  getLibraryStatistics(@Param() { id }: UUIDParamDto): Promise<LibraryStatsResponseDto> {
+    return this.service.getStatistics(id);
   }
 
   @Post(':id/scan')
   @HttpCode(HttpStatus.NO_CONTENT)
-  scanLibrary(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto, @Body() dto: ScanLibraryDto) {
-    return this.service.queueScan(auth, id, dto);
+  scanLibrary(@Param() { id }: UUIDParamDto, @Body() dto: ScanLibraryDto) {
+    return this.service.queueScan(id, dto);
   }
 
   @Post(':id/removeOffline')
   @HttpCode(HttpStatus.NO_CONTENT)
-  removeOfflineFiles(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto) {
-    return this.service.queueRemoveOffline(auth, id);
+  removeOfflineFiles(@Param() { id }: UUIDParamDto) {
+    return this.service.queueRemoveOffline(id);
   }
 }
diff --git a/server/src/infra/repositories/access.repository.ts b/server/src/infra/repositories/access.repository.ts
index 25691846d3..ad650bf0e6 100644
--- a/server/src/infra/repositories/access.repository.ts
+++ b/server/src/infra/repositories/access.repository.ts
@@ -307,10 +307,7 @@ class AuthDeviceAccess implements IAuthDeviceAccess {
 }
 
 class LibraryAccess implements ILibraryAccess {
-  constructor(
-    private libraryRepository: Repository<LibraryEntity>,
-    private partnerRepository: Repository<PartnerEntity>,
-  ) {}
+  constructor(private libraryRepository: Repository<LibraryEntity>) {}
 
   @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
   @ChunkedSet({ paramIndex: 1 })
@@ -329,22 +326,6 @@ class LibraryAccess implements ILibraryAccess {
       })
       .then((libraries) => new Set(libraries.map((library) => library.id)));
   }
-
-  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
-  @ChunkedSet({ paramIndex: 1 })
-  async checkPartnerAccess(userId: string, partnerIds: Set<string>): Promise<Set<string>> {
-    if (partnerIds.size === 0) {
-      return new Set();
-    }
-
-    return this.partnerRepository
-      .createQueryBuilder('partner')
-      .select('partner.sharedById')
-      .where('partner.sharedById IN (:...partnerIds)', { partnerIds: [...partnerIds] })
-      .andWhere('partner.sharedWithId = :userId', { userId })
-      .getMany()
-      .then((partners) => new Set(partners.map((partner) => partner.sharedById)));
-  }
 }
 
 class TimelineAccess implements ITimelineAccess {
@@ -457,7 +438,7 @@ export class AccessRepository implements IAccessRepository {
     this.album = new AlbumAccess(albumRepository, sharedLinkRepository);
     this.asset = new AssetAccess(albumRepository, assetRepository, partnerRepository, sharedLinkRepository);
     this.authDevice = new AuthDeviceAccess(tokenRepository);
-    this.library = new LibraryAccess(libraryRepository, partnerRepository);
+    this.library = new LibraryAccess(libraryRepository);
     this.person = new PersonAccess(assetFaceRepository, personRepository);
     this.partner = new PartnerAccess(partnerRepository);
     this.timeline = new TimelineAccess(partnerRepository);
diff --git a/server/src/infra/sql/access.repository.sql b/server/src/infra/sql/access.repository.sql
index 638be9f90b..a0c4e19275 100644
--- a/server/src/infra/sql/access.repository.sql
+++ b/server/src/infra/sql/access.repository.sql
@@ -196,16 +196,6 @@ WHERE
   )
   AND ("LibraryEntity"."deletedAt" IS NULL)
 
--- AccessRepository.library.checkPartnerAccess
-SELECT
-  "partner"."sharedById" AS "partner_sharedById",
-  "partner"."sharedWithId" AS "partner_sharedWithId"
-FROM
-  "partners" "partner"
-WHERE
-  "partner"."sharedById" IN ($1)
-  AND "partner"."sharedWithId" = $2
-
 -- AccessRepository.person.checkOwnerAccess
 SELECT
   "PersonEntity"."id" AS "PersonEntity_id"
diff --git a/server/test/repositories/access.repository.mock.ts b/server/test/repositories/access.repository.mock.ts
index a1f09aa75c..e10dd7d9a7 100644
--- a/server/test/repositories/access.repository.mock.ts
+++ b/server/test/repositories/access.repository.mock.ts
@@ -42,7 +42,6 @@ export const newAccessRepositoryMock = (reset = true): IAccessRepositoryMock =>
 
     library: {
       checkOwnerAccess: jest.fn().mockResolvedValue(new Set()),
-      checkPartnerAccess: jest.fn().mockResolvedValue(new Set()),
     },
 
     timeline: {
diff --git a/web/src/lib/components/forms/library-user-picker-form.svelte b/web/src/lib/components/forms/library-user-picker-form.svelte
index cc1d31b884..294cf70766 100644
--- a/web/src/lib/components/forms/library-user-picker-form.svelte
+++ b/web/src/lib/components/forms/library-user-picker-form.svelte
@@ -20,7 +20,7 @@
 
   const dispatch = createEventDispatcher<{
     cancel: void;
-    submit: { ownerId: string | null };
+    submit: { ownerId: string };
     delete: void;
   }>();
 
diff --git a/web/src/routes/admin/library-management/+page.svelte b/web/src/routes/admin/library-management/+page.svelte
index e6f4332ee7..1efc7f778f 100644
--- a/web/src/routes/admin/library-management/+page.svelte
+++ b/web/src/routes/admin/library-management/+page.svelte
@@ -28,7 +28,6 @@
     removeOfflineFiles,
     scanLibrary,
     updateLibrary,
-    type CreateLibraryDto,
     type LibraryResponseDto,
     type LibraryStatsResponseDto,
     type UserResponseDto,
@@ -117,14 +116,9 @@
     }
   }
 
-  const handleCreate = async (ownerId: string | null) => {
+  const handleCreate = async (ownerId: string) => {
     try {
-      let createLibraryDto: CreateLibraryDto = { type: LibraryType.External };
-      if (ownerId) {
-        createLibraryDto = { ...createLibraryDto, ownerId };
-      }
-
-      const createdLibrary = await createLibrary({ createLibraryDto });
+      const createdLibrary = await createLibrary({ createLibraryDto: { ownerId, type: LibraryType.External } });
 
       notificationController.show({
         message: `Created library: ${createdLibrary.name}`,