From 265c9d4a59995695a2f3b2ba83854ebc2689cc8f Mon Sep 17 00:00:00 2001 From: Henry Casper Date: Wed, 22 Jul 2026 14:57:10 -0400 Subject: [PATCH 01/10] feat: allow authorized staff users to delete non-default staff roles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Staff users with staffRolePermissions.canRemoveRole can delete non-default StaffRoles from the staff-role details page. Deletion raises a StaffRoleDeletedEvent whose integration handler reassigns every staff user holding the deleted role to the default StaffRole matching the deleted role's enterpriseAppRole (idempotent; missing default role is logged and surfaced as a processing failure). - domain: StaffRole.requestDelete() (visa canRemoveRole, default roles never deletable), StaffRoleDeletedEvent carrying enterpriseAppRole, StaffRoleDeletedReassignmentService, canRemoveRole in UserDomainPermissions and passports; remove legacy deleteAndReassignTo - persistence: StaffUserRepository.getAllAssignedToRole - application-services: StaffRole.delete (replaces delete-and-reassign) - event-handler: staff-role-deleted--reassign-staff-users wired into integration handler registration - graphql: staffRoleDelete mutation + command mapper + resolver tests; isDefault exposed on staff-role detail fragment - ui: red Delete button with Popconfirm on staff-role details page, gated by canRemoveRole and non-default role; progress/failure feedback; navigate back and refetch list on success; Storybook coverage for deletable/default/no-permission/confirmation/pending/failure states - verification: 8 shared Gherkin scenarios implemented across acceptance-api (31/31), acceptance-ui (32/32), and e2e (28/28) with tasks/questions/notes and e2e interactions per contexts/community reference pattern - fix: staff-user.resolvers.test.ts step/feature mismatches (file failed at collection on main, masked by aggregate test counts) - security: clear pnpm audit/snyk gate failures — bump vitest family to 4.1.10, svgo ^3.3.4, fast-uri ^4.1.1, @opentelemetry/propagator-jaeger ^2.9.0, websocket-driver ^0.7.5, axios 1.18.0, ws 8.21.1; extend expired SNYK-JS-OPENTELEMETRYCORE-17373280 ignore to 2026-10-31 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .snyk | 2 +- .../acceptance-api/package.json | 1 + .../staff-role-management.steps.ts | 48 +- .../staff-role/tasks/delete-staff-role.ts | 31 + .../src/mock-application-services.ts | 15 + .../src/shared/abilities/delete-staff-role.ts | 38 + .../src/shared/abilities/index.ts | 1 + .../shared/graphql/staff-role-operations.ts | 11 + .../acceptance-api/src/world.ts | 10 +- .../abilities/mock-staff-role-backend.ts | 55 +- .../staff-role/questions/staff-role-screen.ts | 23 + .../staff-role-management.steps.tsx | 53 +- .../staff-role/tasks/delete-staff-role.ts | 59 + .../staff-role/abilities/staff-user-page.ts | 35 + .../interactions/delete-staff-role-actions.ts | 33 + .../staff-role/questions/staff-role-screen.ts | 25 + .../staff-role/questions/staff-user-screen.ts | 25 + .../staff-role-management.steps.ts | 55 + .../tasks/assign-staff-role-to-user.ts | 47 + .../staff-role/tasks/delete-staff-role.ts | 20 + .../verification-shared/src/pages/index.ts | 2 + .../src/pages/staff-role-form.page.ts | 44 + .../src/pages/staff-user-detail.page.ts | 59 + .../src/pages/staff-users-list.page.ts | 32 + .../staff/staff-role-management.feature | 66 + .../staff-role/delete-and-reassign.test.ts | 162 -- .../user/staff-role/delete-and-reassign.ts | 17 - .../contexts/user/staff-role/delete.test.ts | 114 + .../src/contexts/user/staff-role/delete.ts | 15 + .../features/delete-and-reassign.feature | 18 - .../user/staff-role/features/delete.feature | 16 + .../user/staff-role/features/index.feature | 6 +- .../contexts/user/staff-role/index.test.ts | 22 +- .../src/contexts/user/staff-role/index.ts | 6 +- .../staff-role/features/staff-role.feature | 27 +- .../user/staff-role/staff-role.test.ts | 129 +- .../contexts/user/staff-role/staff-role.ts | 21 +- ...ser-activity-log.entity.additional.test.ts | 1 + .../user/staff-user/staff-user.repository.ts | 1 + .../contexts/user/user.domain-permissions.ts | 1 + .../domain/src/domain/events/types/index.ts | 1 + .../domain/events/types/staff-role-deleted.ts | 13 + .../contexts/member.user.end-user.visa.ts | 1 + .../contexts/member.user.staff-role.visa.ts | 1 + .../contexts/member.user.staff-user.visa.ts | 1 + .../contexts/member.user.vendor-user.visa.ts | 1 + .../features/staff-user.user.passport.feature | 10 + .../contexts/staff-user.user.passport.test.ts | 31 +- .../contexts/staff-user.user.passport.ts | 1 + .../domain/services/features/index.feature | 7 +- .../domain/src/domain/services/index.test.ts | 18 +- .../ocom/domain/src/domain/services/index.ts | 1 + .../services/user/features/index.feature | 6 + ...-role-deleted-reassignment.service.feature | 29 + .../src/domain/services/user/index.test.ts | 29 + .../domain/src/domain/services/user/index.ts | 5 + ...-role-deleted-reassignment.service.test.ts | 177 ++ ...staff-role-deleted-reassignment.service.ts | 48 + .../src/handlers/integration/index.ts | 2 + ...taff-role-deleted--reassign-staff-users.ts | 9 + .../features/staff-role.resolvers.feature | 19 + .../features/staff-user.resolvers.feature | 4 +- .../schema/types/staff-role.command-mapper.ts | 9 +- .../src/schema/types/staff-role.graphql | 9 + .../schema/types/staff-role.resolvers.test.ts | 110 + .../src/schema/types/staff-role.resolvers.ts | 20 +- .../schema/types/staff-user.resolvers.test.ts | 19 +- .../features/staff-user.repository.feature | 10 + .../staff-user/staff-user.repository.test.ts | 48 +- .../user/staff-user/staff-user.repository.ts | 8 +- .../.storybook/preview.tsx | 5 +- .../src/components/staff-role-create.test.tsx | 155 ++ .../src/components/staff-role-create.tsx | 34 +- .../staff-role-edit.container.graphql | 10 + .../staff-role-edit.container.stories.tsx | 159 ++ .../components/staff-role-edit.container.tsx | 27 +- .../components/staff-role-edit.stories.tsx | 106 + .../src/components/staff-user-detail.test.tsx | 6 +- .../tsconfig.vitest.json | 3 + pnpm-lock.yaml | 2440 +++++++++++------ pnpm-workspace.yaml | 24 +- 81 files changed, 3817 insertions(+), 1145 deletions(-) create mode 100644 packages/ocom-verification/acceptance-api/src/contexts/staff-role/tasks/delete-staff-role.ts create mode 100644 packages/ocom-verification/acceptance-api/src/shared/abilities/delete-staff-role.ts create mode 100644 packages/ocom-verification/acceptance-ui/src/contexts/staff-role/tasks/delete-staff-role.ts create mode 100644 packages/ocom-verification/e2e-tests/src/contexts/staff-role/abilities/staff-user-page.ts create mode 100644 packages/ocom-verification/e2e-tests/src/contexts/staff-role/interactions/delete-staff-role-actions.ts create mode 100644 packages/ocom-verification/e2e-tests/src/contexts/staff-role/questions/staff-user-screen.ts create mode 100644 packages/ocom-verification/e2e-tests/src/contexts/staff-role/tasks/assign-staff-role-to-user.ts create mode 100644 packages/ocom-verification/e2e-tests/src/contexts/staff-role/tasks/delete-staff-role.ts create mode 100644 packages/ocom-verification/verification-shared/src/pages/staff-user-detail.page.ts create mode 100644 packages/ocom-verification/verification-shared/src/pages/staff-users-list.page.ts delete mode 100644 packages/ocom/application-services/src/contexts/user/staff-role/delete-and-reassign.test.ts delete mode 100644 packages/ocom/application-services/src/contexts/user/staff-role/delete-and-reassign.ts create mode 100644 packages/ocom/application-services/src/contexts/user/staff-role/delete.test.ts create mode 100644 packages/ocom/application-services/src/contexts/user/staff-role/delete.ts delete mode 100644 packages/ocom/application-services/src/contexts/user/staff-role/features/delete-and-reassign.feature create mode 100644 packages/ocom/application-services/src/contexts/user/staff-role/features/delete.feature create mode 100644 packages/ocom/domain/src/domain/events/types/staff-role-deleted.ts create mode 100644 packages/ocom/domain/src/domain/services/user/features/index.feature create mode 100644 packages/ocom/domain/src/domain/services/user/features/staff-role-deleted-reassignment.service.feature create mode 100644 packages/ocom/domain/src/domain/services/user/index.test.ts create mode 100644 packages/ocom/domain/src/domain/services/user/index.ts create mode 100644 packages/ocom/domain/src/domain/services/user/staff-role-deleted-reassignment.service.test.ts create mode 100644 packages/ocom/domain/src/domain/services/user/staff-role-deleted-reassignment.service.ts create mode 100644 packages/ocom/event-handler/src/handlers/integration/staff-role-deleted--reassign-staff-users.ts create mode 100644 packages/ocom/graphql/src/schema/types/features/staff-role.resolvers.feature create mode 100644 packages/ocom/graphql/src/schema/types/staff-role.resolvers.test.ts create mode 100644 packages/ocom/ui-staff-route-user-management/src/components/staff-role-create.test.tsx create mode 100644 packages/ocom/ui-staff-route-user-management/src/components/staff-role-edit.container.stories.tsx create mode 100644 packages/ocom/ui-staff-route-user-management/tsconfig.vitest.json diff --git a/.snyk b/.snyk index 8037ac1d3..8f9486fb8 100644 --- a/.snyk +++ b/.snyk @@ -162,7 +162,7 @@ ignore: 'SNYK-JS-OPENTELEMETRYCORE-17373280': - '* > @opentelemetry/core': reason: 'The fix requires migrating the Azure Functions telemetry stack from OpenTelemetry 1.x to 2.8.0 or newer. The current Azure exporter and 0.57.x SDK packages require the 1.x API family; a forced major override is type-compatible at build time but leaves mixed SDK internals. Accepted temporarily while the existing OTEL 2.x migration is completed.' - expires: '2026-07-18T00:00:00.000Z' + expires: '2026-10-31T00:00:00.000Z' created: '2026-06-18T00:00:00.000Z' 'SNYK-JS-BRACEEXPANSION-17706650': - '* > brace-expansion@1.1.13': diff --git a/packages/ocom-verification/acceptance-api/package.json b/packages/ocom-verification/acceptance-api/package.json index 06e434cb3..4690c16b1 100644 --- a/packages/ocom-verification/acceptance-api/package.json +++ b/packages/ocom-verification/acceptance-api/package.json @@ -30,6 +30,7 @@ "@ocom/application-services": "workspace:*", "@ocom/context-spec": "workspace:*", "@ocom/data-sources-mongoose-models": "workspace:*", + "@ocom/event-handler": "workspace:*", "@ocom/graphql": "workspace:*", "@ocom/persistence": "workspace:*", "@ocom/service-apollo-server": "workspace:*", diff --git a/packages/ocom-verification/acceptance-api/src/contexts/staff-role/step-definitions/staff-role-management.steps.ts b/packages/ocom-verification/acceptance-api/src/contexts/staff-role/step-definitions/staff-role-management.steps.ts index 61dd39c63..506cb8aea 100644 --- a/packages/ocom-verification/acceptance-api/src/contexts/staff-role/step-definitions/staff-role-management.steps.ts +++ b/packages/ocom-verification/acceptance-api/src/contexts/staff-role/step-definitions/staff-role-management.steps.ts @@ -11,6 +11,7 @@ import { StaffUserNamed } from '../questions/staff-user-named.ts'; import { ViewedStaffRole } from '../questions/viewed-staff-role.ts'; import { AssignStaffRoleToUser } from '../tasks/assign-staff-role-to-user.ts'; import { CreateStaffRole } from '../tasks/create-staff-role.ts'; +import { DeleteStaffRole } from '../tasks/delete-staff-role.ts'; import { EnsureStaffRoleExists } from '../tasks/ensure-staff-role-exists.ts'; import { GrantStaffRolePermission } from '../tasks/grant-staff-role-permission.ts'; import { RenameStaffRole } from '../tasks/rename-staff-role.ts'; @@ -92,6 +93,20 @@ When('{word} assigns the staff role {string} to the staff user {string}', async await actorCalled(actorName).attemptsTo(AssignStaffRoleToUser.assign(roleName).to(staffUserDisplayName)); }); +When('{word} deletes the staff role {string}', async (actorName: string, roleName: string) => { + await actorCalled(actorName).attemptsTo(DeleteStaffRole.named(roleName)); +}); + +When('{word} attempts to delete the staff role {string}', async (actorName: string, roleName: string) => { + const actor = actorCalled(actorName); + await clearStaffRoleOutcomeNotes(actor); + try { + await actor.attemptsTo(DeleteStaffRole.named(roleName)); + } catch (error) { + await actor.attemptsTo(notes().set('lastStaffRoleError', errorMessageOf(error))); + } +}); + Then('the staff roles list should include the default staff roles', async () => { const listed = await actorInTheSpotlight().answer(ListedStaffRoleNames.recorded()); if (!listed) { @@ -141,6 +156,22 @@ Then('the staff role should be updated successfully', async () => { } }); +Then('the staff role should be deleted successfully', async () => { + const status = await actorInTheSpotlight().answer(StaffRoleStatus.of()); + if (status !== 'SUCCESS') { + const capturedError = await actorInTheSpotlight().answer(StaffRoleError.captured()); + throw new Error(`Expected staff role deletion to succeed, but it failed: ${capturedError ?? 'no mutation was performed'}`); + } +}); + +Then('the staff roles list should not include {string}', async (roleName: string) => { + const roles = await actorInTheSpotlight().answer(StaffRolesList.displayed()); + const names = roles.map((role) => role.roleName); + if (names.includes(roleName)) { + throw new Error(`Expected staff roles list to no longer include "${roleName}", but got: [${names.join(', ')}]`); + } +}); + Then('the staff role {string} should have the permission {string} granted', async (roleName: string, permissionKey: string) => { const granted = await actorInTheSpotlight().answer(StaffRolePermission.granted(roleName, permissionKey)); if (!granted) { @@ -149,10 +180,19 @@ Then('the staff role {string} should have the permission {string} granted', asyn }); Then('the staff user {string} should have the staff role {string}', async (staffUserDisplayName: string, roleName: string) => { - const staffUser = await actorInTheSpotlight().answer(StaffUserNamed.called(staffUserDisplayName)); - if (staffUser.role?.roleName !== roleName) { - throw new Error(`Expected staff user "${staffUserDisplayName}" to have role "${roleName}", but got "${staffUser.role?.roleName ?? 'none'}"`); - } + // Integration event handlers run fire-and-forget after the mutation commits, + // so reassignment may complete shortly after the delete response. Poll briefly. + const deadline = Date.now() + 5_000; + let lastSeenRoleName: string | undefined; + while (Date.now() < deadline) { + const staffUser = await actorInTheSpotlight().answer(StaffUserNamed.called(staffUserDisplayName)); + lastSeenRoleName = staffUser.role?.roleName; + if (lastSeenRoleName === roleName) { + return; + } + await new Promise((resolve) => setTimeout(resolve, 250)); + } + throw new Error(`Expected staff user "${staffUserDisplayName}" to have role "${roleName}", but got "${lastSeenRoleName ?? 'none'}"`); }); Then('she should see a staff role error containing {string}', async (expectedFragment: string) => { diff --git a/packages/ocom-verification/acceptance-api/src/contexts/staff-role/tasks/delete-staff-role.ts b/packages/ocom-verification/acceptance-api/src/contexts/staff-role/tasks/delete-staff-role.ts new file mode 100644 index 000000000..da552ecff --- /dev/null +++ b/packages/ocom-verification/acceptance-api/src/contexts/staff-role/tasks/delete-staff-role.ts @@ -0,0 +1,31 @@ +import { type Actor, notes, Task } from '@serenity-js/core'; +import { DeleteStaffRole as DeleteStaffRoleAbility } from '../../../shared/abilities/delete-staff-role.ts'; +import type { StaffRoleNotes } from '../notes/staff-role-notes.ts'; +import { StaffRoleNamed } from '../questions/staff-role-named.ts'; + +/** + * Task that deletes an existing staff role through the API and records the + * outcome in actor notes. + */ +export class DeleteStaffRole extends Task { + static named(roleName: string): DeleteStaffRole { + return new DeleteStaffRole(roleName); + } + + private constructor(private readonly roleName: string) { + super(`deletes the staff role "${roleName}"`); + } + + async performAs(actor: Actor): Promise { + const role = await actor.answer(StaffRoleNamed.called(this.roleName)); + if (!role) { + throw new Error(`Staff role "${this.roleName}" was not found`); + } + + await DeleteStaffRoleAbility.as(actor).performAs(actor, role.id); + + await actor.attemptsTo(notes().set('lastStaffRoleId', role.id), notes().set('lastStaffRoleName', role.roleName), notes().set('lastStaffRoleStatus', 'SUCCESS')); + } + + override toString = () => `deletes the staff role "${this.roleName}"`; +} diff --git a/packages/ocom-verification/acceptance-api/src/mock-application-services.ts b/packages/ocom-verification/acceptance-api/src/mock-application-services.ts index 3a2fedc8b..b2a2a47d2 100644 --- a/packages/ocom-verification/acceptance-api/src/mock-application-services.ts +++ b/packages/ocom-verification/acceptance-api/src/mock-application-services.ts @@ -1,6 +1,7 @@ import type { BlobUploadAuthorizationHeader, BlobUploadCommonResponse, CreateBlobAuthorizationHeaderRequest } from '@cellix/service-blob-storage'; import { type ApplicationServicesFactory, buildApplicationServicesFactory } from '@ocom/application-services'; import type { ApiContextSpec } from '@ocom/context-spec'; +import { RegisterEventHandlers } from '@ocom/event-handler'; import { Persistence } from '@ocom/persistence'; import type { ServiceApolloServer } from '@ocom/service-apollo-server'; import type { BlobAddress, BlobStorageOperations, ClientUploadOperations, ListBlobsRequest, UploadTextBlobRequest } from '@ocom/service-blob-storage'; @@ -21,6 +22,19 @@ type EndUserUpdateQueueMessage = Awaited): void { + if (eventHandlersRegistered) { + return; + } + const { domainDataSource } = dataSourcesFactory.withSystemPassport(); + RegisterEventHandlers(domainDataSource); + eventHandlersRegistered = true; +} + function createMockTokenValidation(): TokenValidation { return { verifyJwt: (token: string): Promise | null> => { @@ -136,6 +150,7 @@ function createRecordingQueueStorageService(): QueueStorageOperations { export function createMockApplicationServicesFactory(serviceMongoose: ServiceMongoose): ApplicationServicesFactory { const dataSourcesFactory = Persistence(serviceMongoose); + registerEventHandlersOnce(dataSourcesFactory); const blobStorageService = createNoOpBlobStorageService(); const clientOperationsService = createNoOpClientOperationsService(); const queueStorageService = createRecordingQueueStorageService(); diff --git a/packages/ocom-verification/acceptance-api/src/shared/abilities/delete-staff-role.ts b/packages/ocom-verification/acceptance-api/src/shared/abilities/delete-staff-role.ts new file mode 100644 index 000000000..666ea69ec --- /dev/null +++ b/packages/ocom-verification/acceptance-api/src/shared/abilities/delete-staff-role.ts @@ -0,0 +1,38 @@ +import { GraphQLClient } from '@cellix/serenity-framework/clients/graphql'; +import { Ability, type Actor } from '@serenity-js/core'; +import { type MutationStatus, STAFF_ROLE_DELETE_MUTATION } from '../graphql/staff-role-operations.ts'; + +/** Handler that performs a staff role deletion for an API actor. */ +type DeleteStaffRoleHandler = (actor: Actor, roleId: string) => Promise; + +/** + * Serenity ability that deletes staff roles through the API verification server. + * Throws when the mutation reports a validation or authorization failure. + */ +export class DeleteStaffRole extends Ability { + constructor(private readonly handler: DeleteStaffRoleHandler) { + super(); + } + + static using(handler: DeleteStaffRoleHandler): DeleteStaffRole { + return new DeleteStaffRole(handler); + } + + async performAs(actor: Actor, roleId: string): Promise { + await this.handler(actor, roleId); + } +} + +export function deleteStaffRoleAbility(): DeleteStaffRole { + return DeleteStaffRole.using(async (actor, roleId) => { + const graphql = GraphQLClient.as(actor); + const response = await graphql.execute(STAFF_ROLE_DELETE_MUTATION, { + input: { id: roleId }, + }); + + const mutationResult = response.data['staffRoleDelete'] as { status: MutationStatus } | undefined; + if (mutationResult?.status?.success !== true) { + throw new Error(String(mutationResult?.status?.errorMessage ?? 'Failed to delete staff role')); + } + }); +} diff --git a/packages/ocom-verification/acceptance-api/src/shared/abilities/index.ts b/packages/ocom-verification/acceptance-api/src/shared/abilities/index.ts index 41d8d8913..15cfbe011 100644 --- a/packages/ocom-verification/acceptance-api/src/shared/abilities/index.ts +++ b/packages/ocom-verification/acceptance-api/src/shared/abilities/index.ts @@ -1,5 +1,6 @@ export { assignStaffRoleAbility } from './assign-staff-role.ts'; export { createCommunityAbility } from './create-community.ts'; export { createStaffRoleAbility } from './create-staff-role.ts'; +export { deleteStaffRoleAbility } from './delete-staff-role.ts'; export { createGraphQLClientAbility } from './graphql-client.ts'; export { updateStaffRoleAbility } from './update-staff-role.ts'; diff --git a/packages/ocom-verification/acceptance-api/src/shared/graphql/staff-role-operations.ts b/packages/ocom-verification/acceptance-api/src/shared/graphql/staff-role-operations.ts index 38e66c807..974c95c95 100644 --- a/packages/ocom-verification/acceptance-api/src/shared/graphql/staff-role-operations.ts +++ b/packages/ocom-verification/acceptance-api/src/shared/graphql/staff-role-operations.ts @@ -150,6 +150,17 @@ export const STAFF_ROLE_UPDATE_MUTATION = ` } `; +export const STAFF_ROLE_DELETE_MUTATION = ` + mutation StaffRoleDelete($input: StaffRoleDeleteInput!) { + staffRoleDelete(input: $input) { + status { + success + errorMessage + } + } + } +`; + export const STAFF_USERS_QUERY = ` query StaffUsers { staffUsers { diff --git a/packages/ocom-verification/acceptance-api/src/world.ts b/packages/ocom-verification/acceptance-api/src/world.ts index f2a1db5e4..1be5b9df4 100644 --- a/packages/ocom-verification/acceptance-api/src/world.ts +++ b/packages/ocom-verification/acceptance-api/src/world.ts @@ -6,6 +6,7 @@ import { infrastructure } from './infrastructure.ts'; import { assignStaffRoleAbility } from './shared/abilities/assign-staff-role.ts'; import { createCommunityAbility } from './shared/abilities/create-community.ts'; import { createStaffRoleAbility } from './shared/abilities/create-staff-role.ts'; +import { deleteStaffRoleAbility } from './shared/abilities/delete-staff-role.ts'; import { createGraphQLClientAbility } from './shared/abilities/graphql-client.ts'; import { updateStaffRoleAbility } from './shared/abilities/update-staff-role.ts'; @@ -19,7 +20,14 @@ export const CellixApiWorld = registerManagedSerenityWorld({ createCast: (state) => new SerenityCast({ useNotepad: true, - abilities: [(actor) => createGraphQLClientAbility(graphqlUrl(state), actor.name), () => createCommunityAbility(), () => createStaffRoleAbility(), () => updateStaffRoleAbility(), () => assignStaffRoleAbility()], + abilities: [ + (actor) => createGraphQLClientAbility(graphqlUrl(state), actor.name), + () => createCommunityAbility(), + () => createStaffRoleAbility(), + () => updateStaffRoleAbility(), + () => deleteStaffRoleAbility(), + () => assignStaffRoleAbility(), + ], }), }); diff --git a/packages/ocom-verification/acceptance-ui/src/contexts/staff-role/abilities/mock-staff-role-backend.ts b/packages/ocom-verification/acceptance-ui/src/contexts/staff-role/abilities/mock-staff-role-backend.ts index 5fd6205b3..aeb81f9cf 100644 --- a/packages/ocom-verification/acceptance-ui/src/contexts/staff-role/abilities/mock-staff-role-backend.ts +++ b/packages/ocom-verification/acceptance-ui/src/contexts/staff-role/abilities/mock-staff-role-backend.ts @@ -1,8 +1,14 @@ import type { MockedResponse } from '@apollo/client/testing'; import { DEFAULT_STAFF_ROLE_NAMES } from '@ocom-verification/verification-shared/test-data'; +import * as GeneratedStaffRoleDocuments from '../../../../../../ocom/ui-staff-route-user-management/src/generated.tsx'; import { StaffRoleByIdDocument, StaffRoleCreateDocument, StaffRolesListDocument, StaffRoleUpdateDocument } from '../../../../../../ocom/ui-staff-route-user-management/src/generated.tsx'; import type { StaffAuth } from '../../../../../../ocom/ui-staff-shared/src/staff-route-shell.tsx'; +// The delete document only exists once the staff-role delete mutation has been +// implemented and code-generated; resolve it dynamically so the remaining +// staff-role scenarios keep running while the delete flow is red. +const StaffRoleDeleteDocument = (GeneratedStaffRoleDocuments as Record)['StaffRoleDeleteDocument'] as typeof StaffRoleByIdDocument | undefined; + /** Business roles supported by the staff portal UI acceptance flows. */ type StaffBusinessRole = 'finance' | 'tech admin' | 'service line owner' | 'case manager'; @@ -53,6 +59,7 @@ interface MockStaffRole { id: string; roleName: string; enterpriseAppRole: string; + isDefault: boolean; createdAt: string; updatedAt: string; permissions: MockPermissions; @@ -134,15 +141,17 @@ let currentCustomAuth: StaffAuth | undefined; let lastMutation: MockMutationResult | undefined; let currentPath = '/'; let idCounter = 0; +// When true, the mocked delete mutation reports a failure instead of deleting. +let deleteShouldFail = false; const nextRoleId = (): string => { idCounter += 1; return idCounter.toString(16).padStart(24, '0'); }; -const addRole = (roleName: string, enterpriseAppRole: string): MockStaffRole => { +const addRole = (roleName: string, enterpriseAppRole: string, isDefault = false): MockStaffRole => { const now = new Date().toISOString(); - const role: MockStaffRole = { id: nextRoleId(), roleName, enterpriseAppRole, createdAt: now, updatedAt: now, permissions: emptyPermissions() }; + const role: MockStaffRole = { id: nextRoleId(), roleName, enterpriseAppRole, isDefault, createdAt: now, updatedAt: now, permissions: emptyPermissions() }; uiRoles.push(role); return role; }; @@ -158,11 +167,17 @@ export function resetStaffRoleUiState(businessRole: StaffBusinessRole): void { currentPath = '/'; currentAuthRole = businessRole; currentCustomAuth = undefined; + deleteShouldFail = false; for (const roleName of DEFAULT_STAFF_ROLE_NAMES) { - addRole(roleName, `Staff.${roleName.replace('Default ', '').replaceAll(' ', '')}`); + addRole(roleName, `Staff.${roleName.replace('Default ', '').replaceAll(' ', '')}`, true); } } +/** Makes the mocked staff-role delete mutation fail for the rest of the scenario. */ +export function failStaffRoleDeletions(): void { + deleteShouldFail = true; +} + /** Overrides the business-role auth with a custom fine-grained StaffAuth. */ export function setScopedStaffAuth(staffAuth: StaffAuth): void { currentCustomAuth = staffAuth; @@ -219,6 +234,7 @@ const toEditFields = (role: MockStaffRole) => ({ id: role.id, roleName: role.roleName, enterpriseAppRole: role.enterpriseAppRole, + isDefault: role.isDefault, permissions: role.permissions, }); @@ -308,4 +324,37 @@ export const buildStaffRoleMocks = (): MockedResponse[] => [ }; }, }, + ...(StaffRoleDeleteDocument + ? [ + { + request: { query: StaffRoleDeleteDocument }, + variableMatcher: () => true, + maxUsageCount: Number.POSITIVE_INFINITY, + result: (variables: { input?: StaffRoleMutationInput }) => { + const role = uiRoles.find((candidate) => candidate.id === variables.input?.id); + if (deleteShouldFail || !role) { + lastMutation = { success: false, errorMessage: deleteShouldFail ? 'Deletion rejected by the server' : 'Staff role not found' }; + return { + data: { + staffRoleDelete: { + __typename: 'StaffRoleDeleteMutationResult' as const, + status: { __typename: 'MutationStatus' as const, success: false, errorMessage: lastMutation.errorMessage }, + }, + }, + }; + } + uiRoles = uiRoles.filter((candidate) => candidate.id !== role.id); + lastMutation = { success: true }; + return { + data: { + staffRoleDelete: { + __typename: 'StaffRoleDeleteMutationResult' as const, + status: { __typename: 'MutationStatus' as const, success: true, errorMessage: null }, + }, + }, + }; + }, + } satisfies MockedResponse, + ] + : []), ]; diff --git a/packages/ocom-verification/acceptance-ui/src/contexts/staff-role/questions/staff-role-screen.ts b/packages/ocom-verification/acceptance-ui/src/contexts/staff-role/questions/staff-role-screen.ts index 2f62fa0a0..416ac5a23 100644 --- a/packages/ocom-verification/acceptance-ui/src/contexts/staff-role/questions/staff-role-screen.ts +++ b/packages/ocom-verification/acceptance-ui/src/contexts/staff-role/questions/staff-role-screen.ts @@ -74,3 +74,26 @@ export const CreateRoleActionVisible = () => Question.about('whether the create /** Question that answers whether any staff role edit action is visible. */ export const AnyEditActionVisible = () => Question.about('whether any staff role edit action is visible', async (actor) => await listPageFor(actor).hasAnyEditAction()); + +/** Question that answers whether the delete action is visible on the details screen. */ +export const DeleteActionVisible = () => Question.about('whether the staff role delete action is visible', async (actor) => await formPageFor(actor).hasDeleteAction()); + +/** Question that reads the text of the currently open delete confirmation. */ +export const DeleteConfirmationText = () => + Question.about('the staff role delete confirmation text', async (actor) => { + const formPage = formPageFor(actor); + await waitUntilUi(() => formPage.deleteConfirmation.isVisible(), 'Expected the delete confirmation to be visible'); + return await formPage.deleteConfirmationText(); + }); + +/** Question that waits for a staff role to disappear from the rendered list. */ +export const StaffRolesListExcludes = (roleName: string) => + Question.about(`whether the staff roles list no longer includes "${roleName}"`, async (actor) => { + const listPage = listPageFor(actor); + try { + await waitUntilUi(async () => !(await listPage.hasRoleNamed(roleName)), `Expected the staff roles list to no longer include "${roleName}"`); + return true; + } catch { + return false; + } + }); diff --git a/packages/ocom-verification/acceptance-ui/src/contexts/staff-role/step-definitions/staff-role-management.steps.tsx b/packages/ocom-verification/acceptance-ui/src/contexts/staff-role/step-definitions/staff-role-management.steps.tsx index 14744c8a1..4fa67b61e 100644 --- a/packages/ocom-verification/acceptance-ui/src/contexts/staff-role/step-definitions/staff-role-management.steps.tsx +++ b/packages/ocom-verification/acceptance-ui/src/contexts/staff-role/step-definitions/staff-role-management.steps.tsx @@ -2,20 +2,24 @@ import { GherkinDataTable } from '@cellix/serenity-framework/cucumber/gherkin-da import { type DataTable, Given, Then, When } from '@cucumber/cucumber'; import { DEFAULT_STAFF_ROLE_NAMES } from '@ocom-verification/verification-shared/test-data'; import { actorCalled, actorInTheSpotlight } from '@serenity-js/core'; -import { ensureMockStaffRole, resetStaffRoleUiState, setScopedStaffAuth } from '../abilities/mock-staff-role-backend.ts'; +import { ensureMockStaffRole, failStaffRoleDeletions, resetStaffRoleUiState, setScopedStaffAuth } from '../abilities/mock-staff-role-backend.ts'; import { BaselineStaffRoleCount, LastStaffRoleMutation, MockedStaffRoleCount } from '../questions/staff-role-outcome.ts'; import { AnyEditActionVisible, CreateRoleActionVisible, + DeleteActionVisible, + DeleteConfirmationText, ErrorFeedbackContaining, FormEnterpriseAppRole, FormRoleNameValue, ListedStaffRoleNames, + StaffRolesListExcludes, StaffRolesListIncludes, SuccessFeedbackVisible, ValidationErrorMatching, } from '../questions/staff-role-screen.ts'; import { CreateStaffRoleViaForm, RenameStaffRoleViaForm, type StaffRoleFormInput } from '../tasks/create-staff-role.ts'; +import { CancelStaffRoleDeletion, DeleteStaffRoleViaForm, StartDeletingStaffRole } from '../tasks/delete-staff-role.ts'; import { OpenStaffRoleEditScreenRecordingRoute, OpenStaffRolesScreenRecordingRoute } from '../tasks/open-staff-role-screens.ts'; import { OpenEditFormForRole, OpenStaffRolesList } from '../tasks/staff-roles-screen.ts'; @@ -39,6 +43,10 @@ Given('a staff role named {string} exists', (roleName: string) => { ensureMockStaffRole(roleName); }); +Given('the staff role deletion will fail', () => { + failStaffRoleDeletions(); +}); + When('{word} views the staff roles list', async (actorName: string) => { await actorCalled(actorName).attemptsTo(OpenStaffRolesList()); }); @@ -69,6 +77,22 @@ When('{word} opens the edit screen for the staff role {string}', async (actorNam await actorCalled(actorName).attemptsTo(OpenStaffRoleEditScreenRecordingRoute(roleName)); }); +When('{word} deletes the staff role {string}', async (actorName: string, roleName: string) => { + await actorCalled(actorName).attemptsTo(DeleteStaffRoleViaForm(roleName)); +}); + +When('{word} attempts to delete the staff role {string}', async (actorName: string, roleName: string) => { + await actorCalled(actorName).attemptsTo(DeleteStaffRoleViaForm(roleName)); +}); + +When('{word} starts deleting the staff role {string}', async (actorName: string, roleName: string) => { + await actorCalled(actorName).attemptsTo(StartDeletingStaffRole(roleName)); +}); + +When('{word} cancels the staff role deletion', async (actorName: string) => { + await actorCalled(actorName).attemptsTo(CancelStaffRoleDeletion()); +}); + Then('the staff roles list should include the default staff roles', async () => { const listed = await actorInTheSpotlight().answer(ListedStaffRoleNames()); const missing = DEFAULT_STAFF_ROLE_NAMES.filter((name) => !listed.includes(name)); @@ -121,6 +145,33 @@ Then('the staff roles list should include {string}', async (roleName: string) => } }); +Then('the staff role should be deleted successfully', async () => { + const actor = actorInTheSpotlight(); + const mutation = await actor.answer(LastStaffRoleMutation()); + if (mutation?.success !== true) { + throw new Error(`Expected the staff role delete mutation to succeed, but got: ${mutation?.errorMessage ?? 'no mutation was performed'}`); + } +}); + +Then('the staff roles list should not include {string}', async (roleName: string) => { + if (!(await actorInTheSpotlight().answer(StaffRolesListExcludes(roleName)))) { + throw new Error(`Expected the staff roles list to no longer include "${roleName}"`); + } +}); + +Then('{word} should not see a delete action for the staff role', async (_actorName: string) => { + if (await actorInTheSpotlight().answer(DeleteActionVisible())) { + throw new Error('Expected the staff role delete action to be hidden, but it is visible'); + } +}); + +Then('{word} should see a delete confirmation explaining assigned staff users will be reassigned', async (_actorName: string) => { + const confirmationText = await actorInTheSpotlight().answer(DeleteConfirmationText()); + if (!/reassigned/i.test(confirmationText) || !/default role/i.test(confirmationText)) { + throw new Error(`Expected the delete confirmation to explain reassignment to the matching default role, but got: "${confirmationText}"`); + } +}); + Then('{word} should see a staff role error containing {string}', async (_actorName: string, expectedFragment: string) => { if (!(await actorInTheSpotlight().answer(ErrorFeedbackContaining(expectedFragment)))) { throw new Error(`Expected a staff role error message containing "${expectedFragment}"`); diff --git a/packages/ocom-verification/acceptance-ui/src/contexts/staff-role/tasks/delete-staff-role.ts b/packages/ocom-verification/acceptance-ui/src/contexts/staff-role/tasks/delete-staff-role.ts new file mode 100644 index 000000000..f816dd8ff --- /dev/null +++ b/packages/ocom-verification/acceptance-ui/src/contexts/staff-role/tasks/delete-staff-role.ts @@ -0,0 +1,59 @@ +import { TaskStep } from '@cellix/serenity-framework/serenity'; +import { type Actor, Task } from '@serenity-js/core'; +import { flushUi, formPageFor, OpenEditFormForRole, waitUntilUi } from './staff-roles-screen.ts'; + +/** + * Task that opens the details (edit) screen of a staff role and clicks the + * delete action, leaving the confirmation Popconfirm open. + */ +export const StartDeletingStaffRole = (roleName: string): Task => + Task.where( + `#actor starts deleting the staff role "${roleName}"`, + new TaskStep(`#actor opens the delete confirmation for "${roleName}"`, async (actor) => { + await actor.attemptsTo(OpenEditFormForRole(roleName)); + const formPage = formPageFor(actor); + await waitUntilUi(() => formPage.deleteRoleButton.isVisible(), `Expected a delete action for the staff role "${roleName}"`); + await formPage.clickDeleteRole(); + await flushUi(); + await waitUntilUi(() => formPage.deleteConfirmation.isVisible(), 'Expected the delete confirmation to appear'); + }), + ); + +/** + * Task that confirms the currently open delete confirmation. + */ +const ConfirmStaffRoleDeletion = (): Task => + Task.where( + '#actor confirms the staff role deletion', + new TaskStep('#actor accepts the delete confirmation', async (actor) => { + const formPage = formPageFor(actor); + await formPage.confirmDelete(); + await flushUi(); + }), + ); + +/** + * Task that cancels the currently open delete confirmation. + */ +export const CancelStaffRoleDeletion = (): Task => + Task.where( + '#actor cancels the staff role deletion', + new TaskStep('#actor dismisses the delete confirmation', async (actor) => { + const formPage = formPageFor(actor); + await formPage.cancelDelete(); + await flushUi(); + }), + ); + +/** + * Task that deletes a staff role through the details screen: opens the role, + * clicks the delete action, and confirms the Popconfirm. + */ +export const DeleteStaffRoleViaForm = (roleName: string): Task => + Task.where( + `#actor deletes the staff role "${roleName}"`, + new TaskStep(`#actor deletes "${roleName}" via the details screen`, async (actor) => { + await actor.attemptsTo(StartDeletingStaffRole(roleName)); + await actor.attemptsTo(ConfirmStaffRoleDeletion()); + }), + ); diff --git a/packages/ocom-verification/e2e-tests/src/contexts/staff-role/abilities/staff-user-page.ts b/packages/ocom-verification/e2e-tests/src/contexts/staff-role/abilities/staff-user-page.ts new file mode 100644 index 000000000..dc6dd5ad3 --- /dev/null +++ b/packages/ocom-verification/e2e-tests/src/contexts/staff-role/abilities/staff-user-page.ts @@ -0,0 +1,35 @@ +import { PlaywrightPageAdapter } from '@cellix/serenity-framework/pages/playwright'; +import { StaffUserDetailPage, StaffUsersListPage } from '@ocom-verification/verification-shared/pages'; +import type { Page } from 'playwright'; +import { waitUntil } from './staff-portal-page.ts'; + +const USERS_LIST_PATH = '/staff/user-management/staff-users'; + +/** Staff users list page object bound to the given browser page. */ +const usersListPageOn = (page: Page): StaffUsersListPage => new StaffUsersListPage(new PlaywrightPageAdapter(page)); + +/** Staff user detail page object bound to the given browser page. */ +export const userDetailPageOn = (page: Page): StaffUserDetailPage => new StaffUserDetailPage(new PlaywrightPageAdapter(page)); + +/** Navigate to the staff users list and wait for the table rows to render. */ +const openUsersList = async (page: Page): Promise => { + await page.goto(USERS_LIST_PATH, { waitUntil: 'networkidle' }); + const listPage = usersListPageOn(page); + await waitUntil(async () => await listPage.heading.isVisible(), 'Timed out waiting for the staff users list to render'); + return listPage; +}; + +/** + * Open the detail screen for a staff user from the users list and wait for the + * assigned-role section to load. Performs a full page load so the screen shows + * fresh (uncached) data. + */ +export const openUserDetailFor = async (page: Page, displayName: string): Promise => { + const listPage = await openUsersList(page); + await listPage.clickEditForUser(displayName); + await page.waitForURL((url) => /\/staff-users\/[^/]+$/.test(url.pathname), { timeout: 20_000 }); + const detailPage = userDetailPageOn(page); + await waitUntil(async () => await detailPage.heading.isVisible(), `Timed out waiting for the staff user detail of "${displayName}" to load`); + await waitUntil(async () => (await detailPage.displayedRoleName()) !== '', `Timed out waiting for the assigned role of "${displayName}" to load`); + return detailPage; +}; diff --git a/packages/ocom-verification/e2e-tests/src/contexts/staff-role/interactions/delete-staff-role-actions.ts b/packages/ocom-verification/e2e-tests/src/contexts/staff-role/interactions/delete-staff-role-actions.ts new file mode 100644 index 000000000..25409c95b --- /dev/null +++ b/packages/ocom-verification/e2e-tests/src/contexts/staff-role/interactions/delete-staff-role-actions.ts @@ -0,0 +1,33 @@ +import { Interaction, the } from '@serenity-js/core'; +import { formPageOn, staffPortalPageOf, waitUntil } from '../abilities/staff-portal-page.ts'; + +/** + * Low-level interaction that clicks the delete action on the staff role + * details (edit) screen, leaving the confirmation Popconfirm open. + */ +export const ClickDeleteStaffRole = () => + Interaction.where(the`#actor clicks the delete staff role action`, async (actor) => { + const page = await staffPortalPageOf(actor); + const formPage = formPageOn(page); + await waitUntil(() => formPage.deleteRoleButton.isVisible(), 'Expected a delete action on the staff role details screen'); + await formPage.clickDeleteRole(); + await waitUntil(() => formPage.deleteConfirmation.isVisible(), 'Expected the delete confirmation to appear'); + }); + +/** + * Low-level interaction that accepts the currently open delete confirmation. + */ +export const ConfirmDeleteStaffRole = () => + Interaction.where(the`#actor confirms the staff role deletion`, async (actor) => { + const page = await staffPortalPageOf(actor); + await formPageOn(page).confirmDelete(); + }); + +/** + * Low-level interaction that dismisses the currently open delete confirmation. + */ +export const CancelDeleteStaffRole = () => + Interaction.where(the`#actor cancels the staff role deletion`, async (actor) => { + const page = await staffPortalPageOf(actor); + await formPageOn(page).cancelDelete(); + }); diff --git a/packages/ocom-verification/e2e-tests/src/contexts/staff-role/questions/staff-role-screen.ts b/packages/ocom-verification/e2e-tests/src/contexts/staff-role/questions/staff-role-screen.ts index 3b179f93f..5673f13eb 100644 --- a/packages/ocom-verification/e2e-tests/src/contexts/staff-role/questions/staff-role-screen.ts +++ b/packages/ocom-verification/e2e-tests/src/contexts/staff-role/questions/staff-role-screen.ts @@ -21,6 +21,31 @@ export const StaffRolesListIncludes = (roleName: string) => return true; }); +/** Waits until the live roles list no longer includes the given role name. */ +export const StaffRolesListExcludes = (roleName: string) => + Question.about(`whether the staff roles list no longer includes "${roleName}"`, async (actor) => { + const page = await staffPortalPageOf(actor as unknown as Actor); + const listPage = await openRolesList(page); + await waitUntil(async () => !(await listPage.hasRoleNamed(roleName)), `Expected staff roles list to no longer include "${roleName}", but got: [${(await listPage.listedRoleNames()).join(', ')}]`); + return true; + }); + +/** Whether the delete action is visible on the staff role details screen. */ +export const DeleteActionVisible = () => + Question.about('whether the staff role delete action is visible', async (actor) => { + const page = await staffPortalPageOf(actor as unknown as Actor); + return await formPageOn(page).hasDeleteAction(); + }); + +/** Waits for the delete confirmation and reads its text. */ +export const DeleteConfirmationText = () => + Question.about('the staff role delete confirmation text', async (actor) => { + const page = await staffPortalPageOf(actor as unknown as Actor); + const formPage = formPageOn(page); + await waitUntil(() => formPage.deleteConfirmation.isVisible(), 'Expected the delete confirmation to be visible'); + return await formPage.deleteConfirmationText(); + }); + /** Waits for the app to navigate back to the staff roles list after a mutation. */ export const ReturnedToStaffRolesList = (failureMessage: string) => Question.about('whether the app returned to the staff roles list', async (actor) => { diff --git a/packages/ocom-verification/e2e-tests/src/contexts/staff-role/questions/staff-user-screen.ts b/packages/ocom-verification/e2e-tests/src/contexts/staff-role/questions/staff-user-screen.ts new file mode 100644 index 000000000..a66dea7f2 --- /dev/null +++ b/packages/ocom-verification/e2e-tests/src/contexts/staff-role/questions/staff-user-screen.ts @@ -0,0 +1,25 @@ +import { type Actor, Question } from '@serenity-js/core'; +import { staffPortalPageOf } from '../abilities/staff-portal-page.ts'; +import { openUserDetailFor } from '../abilities/staff-user-page.ts'; + +/** + * Question that reads the role currently assigned to a staff user, polling + * with fresh page loads until the expected role shows up (staff-role deletion + * reassigns users asynchronously after the delete mutation commits). + */ +export const StaffUserAssignedRole = (displayName: string, expectedRoleName: string) => + Question.about(`the staff role assigned to "${displayName}"`, async (serenityActor) => { + const actor = serenityActor as unknown as Actor; + const page = await staffPortalPageOf(actor); + const deadline = Date.now() + 30_000; + let lastSeenRoleName = ''; + while (Date.now() < deadline) { + const detailPage = await openUserDetailFor(page, displayName); + lastSeenRoleName = await detailPage.displayedRoleName(); + if (lastSeenRoleName === expectedRoleName) { + return lastSeenRoleName; + } + await new Promise((resolve) => setTimeout(resolve, 1_000)); + } + return lastSeenRoleName; + }); diff --git a/packages/ocom-verification/e2e-tests/src/contexts/staff-role/step-definitions/staff-role-management.steps.ts b/packages/ocom-verification/e2e-tests/src/contexts/staff-role/step-definitions/staff-role-management.steps.ts index 57bc833d3..3cf1b7e24 100644 --- a/packages/ocom-verification/e2e-tests/src/contexts/staff-role/step-definitions/staff-role-management.steps.ts +++ b/packages/ocom-verification/e2e-tests/src/contexts/staff-role/step-definitions/staff-role-management.steps.ts @@ -3,17 +3,24 @@ import { AfterAll, type DataTable, Given, Then, When } from '@cucumber/cucumber' import { DEFAULT_STAFF_ROLE_NAMES } from '@ocom-verification/verification-shared/test-data'; import { actorCalled, actorInTheSpotlight } from '@serenity-js/core'; import { closeStaffPortalSessions } from '../../../shared/abilities/staff-portal-session.ts'; +import { OpenEditStaffRoleForm } from '../interactions/open-edit-staff-role-form.ts'; import { BaselineStaffRoleCount, CurrentStaffRoleCount, + DeleteActionVisible, + DeleteConfirmationText, RecordedStaffRoleNames, ReturnedToStaffRolesList, StaffRoleErrorContaining, StaffRolePermissionGranted, + StaffRolesListExcludes, StaffRolesListIncludes, StaffRoleValidationErrorFor, } from '../questions/staff-role-screen.ts'; +import { StaffUserAssignedRole } from '../questions/staff-user-screen.ts'; +import { AssignStaffRoleToUserViaDetail } from '../tasks/assign-staff-role-to-user.ts'; import { CreateStaffRoleViaForm, CreateStaffRoleWithPermissions } from '../tasks/create-staff-role.ts'; +import { CancelStaffRoleDeletion, DeleteStaffRoleViaForm, StartDeletingStaffRole } from '../tasks/delete-staff-role.ts'; import { EnsureStaffRoleExists } from '../tasks/ensure-staff-role-exists.ts'; import { GrantStaffRolePermissionViaForm } from '../tasks/grant-staff-role-permission.ts'; import { OpenStaffRolesScreenRecordingPath } from '../tasks/open-staff-roles-screen.ts'; @@ -58,6 +65,26 @@ When('{word} opens the staff roles screen', async (actorName: string) => { await actorCalled(actorName).attemptsTo(OpenStaffRolesScreenRecordingPath()); }); +When('{word} views the details of the staff role {string}', async (actorName: string, roleName: string) => { + await actorCalled(actorName).attemptsTo(OpenEditStaffRoleForm(roleName)); +}); + +When('{word} assigns the staff role {string} to the staff user {string}', async (actorName: string, roleName: string, staffUserDisplayName: string) => { + await actorCalled(actorName).attemptsTo(AssignStaffRoleToUserViaDetail(roleName, staffUserDisplayName)); +}); + +When('{word} deletes the staff role {string}', async (actorName: string, roleName: string) => { + await actorCalled(actorName).attemptsTo(DeleteStaffRoleViaForm(roleName)); +}); + +When('{word} starts deleting the staff role {string}', async (actorName: string, roleName: string) => { + await actorCalled(actorName).attemptsTo(StartDeletingStaffRole(roleName)); +}); + +When('{word} cancels the staff role deletion', async (actorName: string) => { + await actorCalled(actorName).attemptsTo(CancelStaffRoleDeletion()); +}); + Then('the staff roles list should include the default staff roles', async () => { const listed = await actorInTheSpotlight().answer(RecordedStaffRoleNames()); const missing = DEFAULT_STAFF_ROLE_NAMES.filter((name) => !listed.includes(name)); @@ -78,6 +105,34 @@ Then('the staff roles list should include {string}', async (roleName: string) => await actorInTheSpotlight().answer(StaffRolesListIncludes(roleName)); }); +Then('the staff role should be deleted successfully', async () => { + await actorInTheSpotlight().answer(ReturnedToStaffRolesList('Expected the staff role to be deleted and the app to return to the roles list')); +}); + +Then('the staff roles list should not include {string}', async (roleName: string) => { + await actorInTheSpotlight().answer(StaffRolesListExcludes(roleName)); +}); + +Then('{word} should not see a delete action for the staff role', async (_actorName: string) => { + if (await actorInTheSpotlight().answer(DeleteActionVisible())) { + throw new Error('Expected the staff role delete action to be hidden, but it is visible'); + } +}); + +Then('{word} should see a delete confirmation explaining assigned staff users will be reassigned', async (_actorName: string) => { + const confirmationText = await actorInTheSpotlight().answer(DeleteConfirmationText()); + if (!/reassigned/i.test(confirmationText) || !/default role/i.test(confirmationText)) { + throw new Error(`Expected the delete confirmation to explain reassignment to the matching default role, but got: "${confirmationText}"`); + } +}); + +Then('the staff user {string} should have the staff role {string}', async (staffUserDisplayName: string, roleName: string) => { + const assignedRole = await actorInTheSpotlight().answer(StaffUserAssignedRole(staffUserDisplayName, roleName)); + if (assignedRole !== roleName) { + throw new Error(`Expected staff user "${staffUserDisplayName}" to have the staff role "${roleName}", but got "${assignedRole || 'none'}"`); + } +}); + Then('the staff role {string} should have the permission {string} granted', async (roleName: string, permissionKey: string) => { const granted = await actorInTheSpotlight().answer(StaffRolePermissionGranted(roleName, permissionKey)); if (!granted) { diff --git a/packages/ocom-verification/e2e-tests/src/contexts/staff-role/tasks/assign-staff-role-to-user.ts b/packages/ocom-verification/e2e-tests/src/contexts/staff-role/tasks/assign-staff-role-to-user.ts new file mode 100644 index 000000000..4eba5fdb1 --- /dev/null +++ b/packages/ocom-verification/e2e-tests/src/contexts/staff-role/tasks/assign-staff-role-to-user.ts @@ -0,0 +1,47 @@ +import { Interaction, Task, the } from '@serenity-js/core'; +import { formPageOn, staffPortalPageOf, waitUntil } from '../abilities/staff-portal-page.ts'; +import { openUserDetailFor, userDetailPageOn } from '../abilities/staff-user-page.ts'; + +/** + * Low-level interaction that opens the detail screen of a staff user from the + * staff users list. + */ +const OpenStaffUserDetail = (displayName: string) => + Interaction.where(the`#actor opens the staff user detail of "${displayName}"`, async (actor) => { + const page = await staffPortalPageOf(actor); + await openUserDetailFor(page, displayName); + }); + +/** + * Low-level interaction that picks a role in the assigned-role select of the + * staff user detail screen currently on screen. + */ +const SelectAssignedStaffRole = (roleName: string) => + Interaction.where(the`#actor selects the assigned staff role "${roleName}"`, async (actor) => { + const page = await staffPortalPageOf(actor); + await userDetailPageOn(page).selectRole(roleName); + }); + +/** + * Low-level interaction that saves the assigned-role selection and waits for + * the success feedback. + */ +const SaveAssignedStaffRole = () => + Interaction.where(the`#actor saves the assigned staff role`, async (actor) => { + const page = await staffPortalPageOf(actor); + await userDetailPageOn(page).clickSave(); + const feedback = formPageOn(page); + await waitUntil(() => feedback.successFeedback.isVisible(), 'Expected a success message after assigning the staff role'); + }); + +/** + * Task that assigns a staff role to a staff user through the staff user + * detail screen. + */ +export const AssignStaffRoleToUserViaDetail = (roleName: string, staffUserDisplayName: string) => + Task.where( + the`#actor assigns the staff role "${roleName}" to the staff user "${staffUserDisplayName}" via the staff portal`, + OpenStaffUserDetail(staffUserDisplayName), + SelectAssignedStaffRole(roleName), + SaveAssignedStaffRole(), + ); diff --git a/packages/ocom-verification/e2e-tests/src/contexts/staff-role/tasks/delete-staff-role.ts b/packages/ocom-verification/e2e-tests/src/contexts/staff-role/tasks/delete-staff-role.ts new file mode 100644 index 000000000..093356d58 --- /dev/null +++ b/packages/ocom-verification/e2e-tests/src/contexts/staff-role/tasks/delete-staff-role.ts @@ -0,0 +1,20 @@ +import { Task, the } from '@serenity-js/core'; +import { CancelDeleteStaffRole, ClickDeleteStaffRole, ConfirmDeleteStaffRole } from '../interactions/delete-staff-role-actions.ts'; +import { OpenEditStaffRoleForm } from '../interactions/open-edit-staff-role-form.ts'; + +/** + * Task that deletes a staff role through the details screen: opens the role, + * clicks the delete action, and confirms the Popconfirm. + */ +export const DeleteStaffRoleViaForm = (roleName: string) => Task.where(the`#actor deletes the staff role "${roleName}" via the staff portal`, OpenEditStaffRoleForm(roleName), ClickDeleteStaffRole(), ConfirmDeleteStaffRole()); + +/** + * Task that opens the details screen of a staff role and clicks the delete + * action, leaving the confirmation Popconfirm open. + */ +export const StartDeletingStaffRole = (roleName: string) => Task.where(the`#actor starts deleting the staff role "${roleName}"`, OpenEditStaffRoleForm(roleName), ClickDeleteStaffRole()); + +/** + * Task that cancels the currently open staff role delete confirmation. + */ +export const CancelStaffRoleDeletion = () => Task.where(the`#actor cancels the staff role deletion`, CancelDeleteStaffRole()); diff --git a/packages/ocom-verification/verification-shared/src/pages/index.ts b/packages/ocom-verification/verification-shared/src/pages/index.ts index 92c1e1c6b..3ee21d502 100644 --- a/packages/ocom-verification/verification-shared/src/pages/index.ts +++ b/packages/ocom-verification/verification-shared/src/pages/index.ts @@ -2,3 +2,5 @@ export { CommunityPage } from './community.page.ts'; export { HomePage } from './home.page.ts'; export { STAFF_ROLE_PERMISSION_LABELS, StaffRoleFormPage } from './staff-role-form.page.ts'; export { StaffRolesListPage } from './staff-roles-list.page.ts'; +export { StaffUserDetailPage } from './staff-user-detail.page.ts'; +export { StaffUsersListPage } from './staff-users-list.page.ts'; diff --git a/packages/ocom-verification/verification-shared/src/pages/staff-role-form.page.ts b/packages/ocom-verification/verification-shared/src/pages/staff-role-form.page.ts index f72d1270a..3b27e9095 100644 --- a/packages/ocom-verification/verification-shared/src/pages/staff-role-form.page.ts +++ b/packages/ocom-verification/verification-shared/src/pages/staff-role-form.page.ts @@ -60,6 +60,50 @@ export class StaffRoleFormPage extends AdapterBackedPageObject { return this.adapter.locator('.ant-message-success'); } + /** Red delete action rendered in the upper-right area of the details (edit) screen. */ + get deleteRoleButton(): ElementHandle { + return this.adapter.getByRole('button', { name: /^Delete Role$/ }); + } + + /** Popconfirm content shown after clicking the delete action. */ + get deleteConfirmation(): ElementHandle { + return this.adapter.locator('.ant-popconfirm'); + } + + /** Confirm button inside the delete Popconfirm (scoped to avoid matching form buttons). */ + get confirmDeleteButton(): ElementHandle { + return this.adapter.locator('.ant-popconfirm-buttons .ant-btn-primary'); + } + + /** Cancel button inside the delete Popconfirm (scoped to avoid matching the form cancel button). */ + get cancelDeleteButton(): ElementHandle { + return this.adapter.locator('.ant-popconfirm-buttons .ant-btn:not(.ant-btn-primary)'); + } + + /** Whether the delete action is rendered for the current role/viewer. */ + async hasDeleteAction(): Promise { + return await this.deleteRoleButton.isVisible(); + } + + async clickDeleteRole(): Promise { + await this.deleteRoleButton.click(); + } + + /** Text of the delete confirmation (title + description). */ + async deleteConfirmationText(): Promise { + return (await this.deleteConfirmation.textContent())?.trim() ?? ''; + } + + async confirmDelete(): Promise { + await this.confirmDeleteButton.waitFor({ state: 'visible' }); + await this.confirmDeleteButton.click(); + } + + async cancelDelete(): Promise { + await this.cancelDeleteButton.waitFor({ state: 'visible' }); + await this.cancelDeleteButton.click(); + } + async fillRoleName(value: string): Promise { await this.roleNameInput.fill(value); } diff --git a/packages/ocom-verification/verification-shared/src/pages/staff-user-detail.page.ts b/packages/ocom-verification/verification-shared/src/pages/staff-user-detail.page.ts new file mode 100644 index 000000000..bc7da2ad2 --- /dev/null +++ b/packages/ocom-verification/verification-shared/src/pages/staff-user-detail.page.ts @@ -0,0 +1,59 @@ +import { AdapterBackedPageObject, type ElementHandle } from '@cellix/serenity-framework/pages'; + +/** + * Page object for the staff user detail screen (`/staff/user-management/users/edit/:id`). + * + * Works against both the DOM adapter (component acceptance tests) and the + * Playwright adapter (browser E2E tests). + */ +export class StaffUserDetailPage extends AdapterBackedPageObject { + get heading(): ElementHandle { + return this.adapter.getByText('Staff User Details'); + } + + /** Assigned-role antd Select trigger. */ + get roleSelect(): ElementHandle { + return this.adapter.getByRole('combobox'); + } + + get saveButton(): ElementHandle { + return this.adapter.getByRole('button', { name: /^Save$/ }); + } + + /** + * Role name currently shown by the assigned-role select — the selected + * option label when a selection exists, otherwise the placeholder (which + * the screen sets to the persisted role name). Handles both the antd v5 + * (`selection-item`) and antd v6 (`content`) select markup. + */ + async displayedRoleName(): Promise { + const selection = this.adapter.locator('.ant-select-selection-item, .ant-select-content'); + if (await selection.isVisible()) { + const title = await selection.getAttribute('title'); + if (title) { + return title; + } + const text = (await selection.textContent())?.trim(); + if (text) { + return text; + } + } + const placeholder = this.adapter.locator('.ant-select-selection-placeholder, .ant-select-placeholder'); + if (await placeholder.isVisible()) { + return (await placeholder.textContent())?.trim() ?? ''; + } + return ''; + } + + /** Open the assigned-role dropdown and pick the option with the given role name. */ + async selectRole(roleName: string): Promise { + await this.roleSelect.click(); + const option = this.adapter.locator(`.ant-select-item-option[title="${roleName}"]`); + await option.waitFor({ state: 'visible' }); + await option.click(); + } + + async clickSave(): Promise { + await this.saveButton.click(); + } +} diff --git a/packages/ocom-verification/verification-shared/src/pages/staff-users-list.page.ts b/packages/ocom-verification/verification-shared/src/pages/staff-users-list.page.ts new file mode 100644 index 000000000..8d7c2c5dc --- /dev/null +++ b/packages/ocom-verification/verification-shared/src/pages/staff-users-list.page.ts @@ -0,0 +1,32 @@ +import { AdapterBackedPageObject, type ElementHandle } from '@cellix/serenity-framework/pages'; + +/** + * Page object for the staff users list screen (`/staff/user-management/users`). + * + * Works against both the DOM adapter (component acceptance tests) and the + * Playwright adapter (browser E2E tests). + */ +export class StaffUsersListPage extends AdapterBackedPageObject { + get heading(): ElementHandle { + return this.adapter.getByText(/Staff Users \(/); + } + + /** Click the row-level Edit action for the staff user with the given display name. */ + async clickEditForUser(displayName: string): Promise { + const rows = await this.adapter.locatorAll('.ant-table-tbody tr.ant-table-row'); + for (const row of rows) { + const text = await row.textContent(); + if (text?.includes(displayName)) { + const buttons = await row.querySelectorAll('button, a'); + for (const button of buttons) { + const label = await button.textContent(); + if (label?.trim() === 'Edit') { + await button.click(); + return; + } + } + } + } + throw new Error(`No Edit action found for staff user "${displayName}"`); + } +} diff --git a/packages/ocom-verification/verification-shared/src/scenarios/staff/staff-role-management.feature b/packages/ocom-verification/verification-shared/src/scenarios/staff/staff-role-management.feature index c24a4abfc..5d1543efe 100644 --- a/packages/ocom-verification/verification-shared/src/scenarios/staff/staff-role-management.feature +++ b/packages/ocom-verification/verification-shared/src/scenarios/staff/staff-role-management.feature @@ -127,3 +127,69 @@ Feature: Staff role management And a staff role named "Restricted Role" exists When Alice opens the edit screen for the staff role "Restricted Role" Then Alice should be directed to "/unauthorized" + + Scenario: Delete a non-default staff role + Given Alice is an authenticated "tech admin" staff user + And a staff role named "Obsolete Coordinator" exists + When Alice deletes the staff role "Obsolete Coordinator" + Then the staff role should be deleted successfully + And the staff roles list should not include "Obsolete Coordinator" + + @skip-ui + Scenario: Deleting a staff role reassigns its staff users to the matching default role + Given Alice is an authenticated "tech admin" staff user + And a staff role named "Interim Case Manager" exists + And Alice assigns the staff role "Interim Case Manager" to the staff user "Staff User" + When Alice deletes the staff role "Interim Case Manager" + Then the staff role should be deleted successfully + And the staff user "Staff User" should have the staff role "Default Case Manager" + + @api-only + Scenario: Default staff roles cannot be deleted + Given Alice is an authenticated "tech admin" staff user + And a staff role named "Default Case Manager" exists + When Alice attempts to delete the staff role "Default Case Manager" + Then she should see a staff role error containing "default" + And the staff roles list should include "Default Case Manager" + + @skip-api + Scenario: The delete action is not available for a default staff role + Given Alice is an authenticated "tech admin" staff user + And a staff role named "Default Case Manager" exists + When Alice views the details of the staff role "Default Case Manager" + Then she should not see a delete action for the staff role + + @api-only + Scenario: Staff user without the remove-role permission cannot delete a staff role + Given Alice is an authenticated "case manager" staff user + And a staff role named "Seeded Case Manager" exists + When Alice attempts to delete the staff role "Seeded Case Manager" + Then she should see a staff role error containing "do not have permission" + And the staff roles list should include "Seeded Case Manager" + + @ui-only + Scenario: Staff user without the remove-role permission sees no delete action + Given Alice is an authenticated staff user with only the "canEditRole" role permission + And a staff role named "Guarded Role" exists + When Alice views the details of the staff role "Guarded Role" + Then she should not see a delete action for the staff role + + @skip-api + Scenario: Cancelling the delete confirmation leaves the staff role intact + Given Alice is an authenticated "tech admin" staff user + And a staff role named "Retained Role" exists + When Alice starts deleting the staff role "Retained Role" + Then she should see a delete confirmation explaining assigned staff users will be reassigned + When Alice cancels the staff role deletion + And Alice views the staff roles list + Then the staff roles list should include "Retained Role" + + @ui-only + Scenario: Deletion failure keeps the staff role and shows an error + Given Alice is an authenticated "tech admin" staff user + And a staff role named "Resilient Role" exists + And the staff role deletion will fail + When Alice attempts to delete the staff role "Resilient Role" + Then she should see a staff role error containing "Failed to delete" + When Alice views the staff roles list + Then the staff roles list should include "Resilient Role" diff --git a/packages/ocom/application-services/src/contexts/user/staff-role/delete-and-reassign.test.ts b/packages/ocom/application-services/src/contexts/user/staff-role/delete-and-reassign.test.ts deleted file mode 100644 index c282fd33d..000000000 --- a/packages/ocom/application-services/src/contexts/user/staff-role/delete-and-reassign.test.ts +++ /dev/null @@ -1,162 +0,0 @@ -import path from 'node:path'; -import { fileURLToPath } from 'node:url'; -import { describeFeature, loadFeature } from '@amiceli/vitest-cucumber'; -import type { Domain } from '@ocom/domain'; -import type { DataSources } from '@ocom/persistence'; -import { expect, vi } from 'vitest'; -import { deleteAndReassign } from './delete-and-reassign.ts'; - -const test = { for: describeFeature }; -const __dirname = path.dirname(fileURLToPath(import.meta.url)); -const feature = await loadFeature(path.resolve(__dirname, 'features/delete-and-reassign.feature')); - -function makeMockStaffRole(overrides: Partial = {}) { - const baseRole = { - id: '507f1f77bcf86cd799439011', - roleName: 'Test Role', - isDefault: false, - permissions: { - communityPermissions: { - canManageStaffRolesAndPermissions: false, - canManageAllCommunities: false, - canDeleteCommunities: false, - canChangeCommunityOwner: false, - canReIndexSearchCollections: false, - }, - }, - roleType: null, - createdAt: new Date(), - updatedAt: new Date(), - schemaVersion: '1.0', - ...overrides, - }; - - // Return a mock StaffRole object with the deleteAndReassignTo method - return { - ...baseRole, - deleteAndReassignTo: vi.fn(), - } as unknown as Domain.Contexts.User.StaffRole.StaffRole; -} - -function makeMockRepo(overrides: Partial> = {}) { - return { - getById: vi.fn(), - save: vi.fn(), - ...overrides, - } as unknown as Domain.Contexts.User.StaffRole.StaffRoleRepository; -} - -test.for(feature, ({ Scenario, BeforeEachScenario }) => { - let dataSources: DataSources; - let deleteAndReassignRole: (command: { roleId: string; reassignToRoleId: string }) => Promise; - - BeforeEachScenario(() => { - dataSources = { - domainDataSource: { - User: { - StaffRole: { - StaffRoleUnitOfWork: { - withScopedTransaction: vi.fn(), - }, - }, - }, - }, - } as unknown as DataSources; - - deleteAndReassignRole = deleteAndReassign(dataSources); - }); - - Scenario('Deleting and reassigning a staff role successfully', ({ Given, When, Then }) => { - Given('a staff role with id "507f1f77bcf86cd799439011" exists', () => { - // Mock will be set up in When step - }); - - Given('a staff role with id "507f1f77bcf86cd799439012" exists', () => { - // Mock will be set up in When step - }); - - When('I delete and reassign role "507f1f77bcf86cd799439011" to role "507f1f77bcf86cd799439012"', async () => { - const roleToDelete = makeMockStaffRole({ id: '507f1f77bcf86cd799439011' }); - const roleToAssign = makeMockStaffRole({ id: '507f1f77bcf86cd799439012' }); - - const mockRepo = makeMockRepo({ - getById: vi.fn().mockResolvedValueOnce(roleToDelete).mockResolvedValueOnce(roleToAssign), - save: vi.fn().mockResolvedValue(roleToDelete), - }); - - vi.mocked(dataSources.domainDataSource.User.StaffRole.StaffRoleUnitOfWork.withScopedTransaction).mockImplementation(async (callback) => { - await callback(mockRepo); - }); - - await deleteAndReassignRole({ roleId: '507f1f77bcf86cd799439011', reassignToRoleId: '507f1f77bcf86cd799439012' }); - }); - - Then('the operation should complete successfully', () => { - // If no error was thrown, the test passes - expect(true).toBe(true); - }); - }); - - Scenario('Deleting a staff role that does not exist', ({ Given, When, Then }) => { - let error: Error; - - Given('no staff role with id "507f1f77bcf86cd799439011" exists', () => { - // Mock will be set up in When step - }); - - When('I delete and reassign role "507f1f77bcf86cd799439011" to role "507f1f77bcf86cd799439012"', async () => { - const mockRepo = makeMockRepo({ - getById: vi.fn().mockRejectedValue(new Error('Not found')), - }); - - vi.mocked(dataSources.domainDataSource.User.StaffRole.StaffRoleUnitOfWork.withScopedTransaction).mockImplementation(async (callback) => { - await callback(mockRepo); - }); - - try { - await deleteAndReassignRole({ roleId: '507f1f77bcf86cd799439011', reassignToRoleId: '507f1f77bcf86cd799439012' }); - } catch (err) { - error = err as Error; - } - }); - - Then('it should throw an error', () => { - expect(error).toBeDefined(); - }); - }); - - Scenario('Reassigning to a staff role that does not exist', ({ Given, When, Then }) => { - let error: Error; - - Given('a staff role with id "507f1f77bcf86cd799439011" exists', () => { - // Mock will be set up in When step - }); - - Given('no staff role with id "507f1f77bcf86cd799439012" exists', () => { - // Mock will be set up in When step - }); - - When('I delete and reassign role "507f1f77bcf86cd799439011" to role "507f1f77bcf86cd799439012"', async () => { - const roleToDelete = makeMockStaffRole({ id: '507f1f77bcf86cd799439011' }); - - const mockRepo = makeMockRepo({ - save: vi.fn().mockResolvedValue(roleToDelete), - getById: vi.fn().mockResolvedValueOnce(roleToDelete).mockRejectedValueOnce(new Error('Not found')), - }); - - vi.mocked(dataSources.domainDataSource.User.StaffRole.StaffRoleUnitOfWork.withScopedTransaction).mockImplementation(async (callback) => { - await callback(mockRepo); - }); - - try { - await deleteAndReassignRole({ roleId: '507f1f77bcf86cd799439011', reassignToRoleId: '507f1f77bcf86cd799439012' }); - } catch (err) { - error = err as Error; - } - }); - - Then('it should throw an error', () => { - expect(error).toBeDefined(); - }); - }); -}); diff --git a/packages/ocom/application-services/src/contexts/user/staff-role/delete-and-reassign.ts b/packages/ocom/application-services/src/contexts/user/staff-role/delete-and-reassign.ts deleted file mode 100644 index 505b65faa..000000000 --- a/packages/ocom/application-services/src/contexts/user/staff-role/delete-and-reassign.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { DataSources } from '@ocom/persistence'; - -export interface StaffRoleDeleteAndReassignCommand { - roleId: string; - reassignToRoleId: string; -} - -export const deleteAndReassign = (dataSources: DataSources) => { - return async (command: StaffRoleDeleteAndReassignCommand): Promise => { - await dataSources.domainDataSource.User.StaffRole.StaffRoleUnitOfWork.withScopedTransaction(async (repository) => { - const roleToDelete = await repository.getById(command.roleId); - const roleToAssign = await repository.getById(command.reassignToRoleId); - roleToDelete.deleteAndReassignTo(roleToAssign); - await repository.save(roleToDelete); - }); - }; -}; diff --git a/packages/ocom/application-services/src/contexts/user/staff-role/delete.test.ts b/packages/ocom/application-services/src/contexts/user/staff-role/delete.test.ts new file mode 100644 index 000000000..66ba39284 --- /dev/null +++ b/packages/ocom/application-services/src/contexts/user/staff-role/delete.test.ts @@ -0,0 +1,114 @@ +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { describeFeature, loadFeature } from '@amiceli/vitest-cucumber'; +import type { Domain } from '@ocom/domain'; +import type { DataSources } from '@ocom/persistence'; +import { expect, vi } from 'vitest'; +import { deleteStaffRole } from './delete.ts'; + +const test = { for: describeFeature }; +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const feature = await loadFeature(path.resolve(__dirname, 'features/delete.feature')); + +function makeMockStaffRole() { + return { + id: '507f1f77bcf86cd799439011', + roleName: 'Test Role', + isDefault: false, + requestDelete: vi.fn(), + } as unknown as Domain.Contexts.User.StaffRole.StaffRole; +} + +test.for(feature, ({ Scenario, BeforeEachScenario }) => { + let dataSources: DataSources; + let deleteRole: (command: { roleId: string }) => Promise; + let mockRepo: { + getById: ReturnType; + save: ReturnType; + }; + let mockRole: ReturnType; + let thrownError: Error | null; + + BeforeEachScenario(() => { + thrownError = null; + mockRole = makeMockStaffRole(); + mockRepo = { + getById: vi.fn(), + save: vi.fn(async (role: unknown) => role), + }; + dataSources = { + domainDataSource: { + User: { + StaffRole: { + StaffRoleUnitOfWork: { + withScopedTransaction: vi.fn(async (fn: (repo: typeof mockRepo) => Promise) => { + await fn(mockRepo); + }), + }, + }, + }, + }, + } as unknown as DataSources; + + deleteRole = deleteStaffRole(dataSources); + }); + + Scenario('Deleting a staff role successfully', ({ Given, When, Then }) => { + Given('a staff role with id "507f1f77bcf86cd799439011" exists', () => { + mockRepo.getById.mockResolvedValue(mockRole); + }); + + When('I delete role "507f1f77bcf86cd799439011"', async () => { + await deleteRole({ roleId: '507f1f77bcf86cd799439011' }); + }); + + Then('the role should be marked for deletion and saved', () => { + expect(mockRepo.getById).toHaveBeenCalledWith('507f1f77bcf86cd799439011'); + expect(mockRole.requestDelete).toHaveBeenCalledTimes(1); + expect(mockRepo.save).toHaveBeenCalledWith(mockRole); + }); + }); + + Scenario('Deleting a staff role that does not exist', ({ Given, When, Then }) => { + Given('no staff role with id "507f1f77bcf86cd799439011" exists', () => { + mockRepo.getById.mockRejectedValue(new Error('StaffRole with id 507f1f77bcf86cd799439011 not found')); + }); + + When('I try to delete role "507f1f77bcf86cd799439011"', async () => { + try { + await deleteRole({ roleId: '507f1f77bcf86cd799439011' }); + } catch (error) { + thrownError = error as Error; + } + }); + + Then('it should throw an error', () => { + expect(thrownError).not.toBeNull(); + expect(thrownError?.message).toContain('not found'); + expect(mockRepo.save).not.toHaveBeenCalled(); + }); + }); + + Scenario('Deleting a staff role the domain refuses to delete', ({ Given, When, Then }) => { + Given('a staff role with id "507f1f77bcf86cd799439011" exists whose deletion is not permitted', () => { + mockRole = makeMockStaffRole(); + (mockRole.requestDelete as ReturnType).mockImplementation(() => { + throw new Error('You do not have permission to delete this role'); + }); + mockRepo.getById.mockResolvedValue(mockRole); + }); + + When('I try to delete role "507f1f77bcf86cd799439011"', async () => { + try { + await deleteRole({ roleId: '507f1f77bcf86cd799439011' }); + } catch (error) { + thrownError = error as Error; + } + }); + + Then('it should throw a permission error and not save the role', () => { + expect(thrownError?.message).toContain('do not have permission'); + expect(mockRepo.save).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/packages/ocom/application-services/src/contexts/user/staff-role/delete.ts b/packages/ocom/application-services/src/contexts/user/staff-role/delete.ts new file mode 100644 index 000000000..d4e2e2953 --- /dev/null +++ b/packages/ocom/application-services/src/contexts/user/staff-role/delete.ts @@ -0,0 +1,15 @@ +import type { DataSources } from '@ocom/persistence'; + +export interface StaffRoleDeleteCommand { + roleId: string; +} + +export const deleteStaffRole = (dataSources: DataSources) => { + return async (command: StaffRoleDeleteCommand): Promise => { + await dataSources.domainDataSource.User.StaffRole.StaffRoleUnitOfWork.withScopedTransaction(async (repository) => { + const roleToDelete = await repository.getById(command.roleId); + roleToDelete.requestDelete(); + await repository.save(roleToDelete); + }); + }; +}; diff --git a/packages/ocom/application-services/src/contexts/user/staff-role/features/delete-and-reassign.feature b/packages/ocom/application-services/src/contexts/user/staff-role/features/delete-and-reassign.feature deleted file mode 100644 index 096d315fd..000000000 --- a/packages/ocom/application-services/src/contexts/user/staff-role/features/delete-and-reassign.feature +++ /dev/null @@ -1,18 +0,0 @@ -Feature: Deleting and reassigning a staff role - - Scenario: Deleting and reassigning a staff role successfully - Given a staff role with id "507f1f77bcf86cd799439011" exists - Given a staff role with id "507f1f77bcf86cd799439012" exists - When I delete and reassign role "507f1f77bcf86cd799439011" to role "507f1f77bcf86cd799439012" - Then the operation should complete successfully - - Scenario: Deleting a staff role that does not exist - Given no staff role with id "507f1f77bcf86cd799439011" exists - When I delete and reassign role "507f1f77bcf86cd799439011" to role "507f1f77bcf86cd799439012" - Then it should throw an error - - Scenario: Reassigning to a staff role that does not exist - Given a staff role with id "507f1f77bcf86cd799439011" exists - Given no staff role with id "507f1f77bcf86cd799439012" exists - When I delete and reassign role "507f1f77bcf86cd799439011" to role "507f1f77bcf86cd799439012" - Then it should throw an error \ No newline at end of file diff --git a/packages/ocom/application-services/src/contexts/user/staff-role/features/delete.feature b/packages/ocom/application-services/src/contexts/user/staff-role/features/delete.feature new file mode 100644 index 000000000..81eb36b33 --- /dev/null +++ b/packages/ocom/application-services/src/contexts/user/staff-role/features/delete.feature @@ -0,0 +1,16 @@ +Feature: Deleting a staff role + + Scenario: Deleting a staff role successfully + Given a staff role with id "507f1f77bcf86cd799439011" exists + When I delete role "507f1f77bcf86cd799439011" + Then the role should be marked for deletion and saved + + Scenario: Deleting a staff role that does not exist + Given no staff role with id "507f1f77bcf86cd799439011" exists + When I try to delete role "507f1f77bcf86cd799439011" + Then it should throw an error + + Scenario: Deleting a staff role the domain refuses to delete + Given a staff role with id "507f1f77bcf86cd799439011" exists whose deletion is not permitted + When I try to delete role "507f1f77bcf86cd799439011" + Then it should throw a permission error and not save the role diff --git a/packages/ocom/application-services/src/contexts/user/staff-role/features/index.feature b/packages/ocom/application-services/src/contexts/user/staff-role/features/index.feature index 0e049477d..47b05bd23 100644 --- a/packages/ocom/application-services/src/contexts/user/staff-role/features/index.feature +++ b/packages/ocom/application-services/src/contexts/user/staff-role/features/index.feature @@ -5,10 +5,10 @@ Feature: Staff Role Application Service When I create a staff role with name "Test Role" Then it should delegate to the create function - Scenario: Deleting and reassigning a staff role through the application service + Scenario: Deleting a staff role through the application service Given a staff role application service - When I delete and reassign role "role1" to role "role2" - Then it should delegate to the deleteAndReassign function + When I delete role "role1" + Then it should delegate to the delete function Scenario: Querying a staff role by ID through the application service Given a staff role application service diff --git a/packages/ocom/application-services/src/contexts/user/staff-role/index.test.ts b/packages/ocom/application-services/src/contexts/user/staff-role/index.test.ts index 5ce2ac106..8bc821a8b 100644 --- a/packages/ocom/application-services/src/contexts/user/staff-role/index.test.ts +++ b/packages/ocom/application-services/src/contexts/user/staff-role/index.test.ts @@ -1,17 +1,17 @@ import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { describeFeature, loadFeature } from '@amiceli/vitest-cucumber'; -import { expect, vi } from 'vitest'; import type { Domain } from '@ocom/domain'; import type { DataSources } from '@ocom/persistence'; +import { expect, vi } from 'vitest'; // Mock the individual service modules vi.mock('./create.ts', () => ({ create: vi.fn(), })); -vi.mock('./delete-and-reassign.ts', () => ({ - deleteAndReassign: vi.fn(), +vi.mock('./delete.ts', () => ({ + deleteStaffRole: vi.fn(), })); vi.mock('./query-by-id.ts', () => ({ @@ -22,9 +22,9 @@ vi.mock('./query-by-role-name.ts', () => ({ queryByRoleName: vi.fn(), })); -import { StaffRole } from './index.ts'; import { create } from './create.ts'; -import { deleteAndReassign } from './delete-and-reassign.ts'; +import { deleteStaffRole } from './delete.ts'; +import { StaffRole } from './index.ts'; import { queryById } from './query-by-id.ts'; import { queryByRoleName } from './query-by-role-name.ts'; @@ -64,12 +64,12 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { // Set up mock implementations const mockCreateFn = vi.fn().mockResolvedValue(makeMockStaffRole({ roleName: 'Test Role' })); - const mockDeleteAndReassignFn = vi.fn().mockResolvedValue(undefined); + const mockDeleteFn = vi.fn().mockResolvedValue(undefined); const mockQueryByIdFn = vi.fn().mockResolvedValue(makeMockStaffRole({ id: 'role1' })); const mockQueryByRoleNameFn = vi.fn().mockResolvedValue(makeMockStaffRole({ roleName: 'Test Role' })); vi.mocked(create).mockReturnValue(mockCreateFn); - vi.mocked(deleteAndReassign).mockReturnValue(mockDeleteAndReassignFn); + vi.mocked(deleteStaffRole).mockReturnValue(mockDeleteFn); vi.mocked(queryById).mockReturnValue(mockQueryByIdFn); vi.mocked(queryByRoleName).mockReturnValue(mockQueryByRoleNameFn); @@ -105,16 +105,16 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { }); }); - Scenario('Deleting and reassigning a staff role through the application service', ({ Given, When, Then }) => { + Scenario('Deleting a staff role through the application service', ({ Given, When, Then }) => { Given('a staff role application service', () => { expect(service).toBeDefined(); }); - When('I delete and reassign role "role1" to role "role2"', async () => { - await service.deleteAndReassign({ roleId: 'role1', reassignToRoleId: 'role2' }); + When('I delete role "role1"', async () => { + await service.delete({ roleId: 'role1' }); }); - Then('it should delegate to the deleteAndReassign function', () => { + Then('it should delegate to the delete function', () => { // If no error was thrown, the delegation worked expect(true).toBe(true); }); diff --git a/packages/ocom/application-services/src/contexts/user/staff-role/index.ts b/packages/ocom/application-services/src/contexts/user/staff-role/index.ts index 73f72b3ec..1a120c527 100644 --- a/packages/ocom/application-services/src/contexts/user/staff-role/index.ts +++ b/packages/ocom/application-services/src/contexts/user/staff-role/index.ts @@ -2,7 +2,7 @@ import type { Domain } from '@ocom/domain'; import type { DataSources } from '@ocom/persistence'; import { create, type StaffRoleCreateCommand } from './create.ts'; import { createDefaultRoles } from './create-default-roles.ts'; -import { deleteAndReassign, type StaffRoleDeleteAndReassignCommand } from './delete-and-reassign.ts'; +import { deleteStaffRole, type StaffRoleDeleteCommand } from './delete.ts'; import { list } from './list.ts'; import { queryById, type StaffRoleQueryByIdCommand } from './query-by-id.ts'; import { queryByRoleName, type StaffRoleQueryByRoleNameCommand } from './query-by-role-name.ts'; @@ -11,7 +11,7 @@ import { type StaffRoleUpdateCommand, update } from './update.ts'; export interface StaffRoleApplicationService { create: (command: StaffRoleCreateCommand) => Promise; createDefaultRoles: () => Promise; - deleteAndReassign: (command: StaffRoleDeleteAndReassignCommand) => Promise; + delete: (command: StaffRoleDeleteCommand) => Promise; list: () => Promise; queryById: (command: StaffRoleQueryByIdCommand) => Promise; queryByRoleName: (command: StaffRoleQueryByRoleNameCommand) => Promise; @@ -22,7 +22,7 @@ export const StaffRole = (dataSources: DataSources): StaffRoleApplicationService return { create: create(dataSources), createDefaultRoles: createDefaultRoles(dataSources), - deleteAndReassign: deleteAndReassign(dataSources), + delete: deleteStaffRole(dataSources), list: list(dataSources), queryById: queryById(dataSources), queryByRoleName: queryByRoleName(dataSources), diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role.feature b/packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role.feature index b751e6feb..b0ff52800 100644 --- a/packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role.feature +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/features/staff-role.feature @@ -46,24 +46,29 @@ Feature: StaffRole When I try to set isDefault to true Then a PermissionError should be thrown - # deleteAndReassignTo - Scenario: Deleting a non-default staff role with permission - Given a StaffRole aggregate that is not deleted and is not default, with permission to manage staff roles and permissions - When I call deleteAndReassignTo with a valid StaffRoleEntityReference + # requestDelete + Scenario: Deleting a non-default staff role with the remove-role permission + Given a StaffRole aggregate that is not deleted and is not default, with permission to remove staff roles + When I call requestDelete Then the staff role should be marked as deleted - And a RoleDeletedReassignEvent should be added to integration events + And a StaffRoleDeletedEvent should be added to integration events - Scenario: Deleting a non-default staff role without permission - Given a StaffRole aggregate that is not deleted and is not default, without permission to manage staff roles and permissions - When I try to call deleteAndReassignTo with a valid StaffRoleEntityReference + Scenario: Deleting a non-default staff role without the remove-role permission + Given a StaffRole aggregate that is not deleted and is not default, without permission to remove staff roles + When I try to call requestDelete Then a PermissionError should be thrown - And no RoleDeletedReassignEvent should be emitted + And no StaffRoleDeletedEvent should be emitted Scenario: Deleting a default staff role Given a StaffRole aggregate that is default - When I try to call deleteAndReassignTo with a valid StaffRoleEntityReference + When I try to call requestDelete Then a PermissionError should be thrown - And no RoleDeletedReassignEvent should be emitted + And no StaffRoleDeletedEvent should be emitted + + Scenario: Deleting an already deleted staff role is idempotent + Given a StaffRole aggregate that is already deleted, with permission to remove staff roles + When I call requestDelete again + Then no additional StaffRoleDeletedEvent should be emitted # permissions (delegation) Scenario: Accessing permissions entity diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.test.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.test.ts index bf2553dd2..16c5c6816 100644 --- a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.test.ts +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.test.ts @@ -3,20 +3,20 @@ import { fileURLToPath } from 'node:url'; import { describeFeature, loadFeature } from '@amiceli/vitest-cucumber'; import { PermissionError } from '@cellix/domain-seedwork/domain-entity'; import { expect, vi } from 'vitest'; -import { RoleDeletedReassignEvent } from '../../../events/types/role-deleted-reassign.ts'; +import { StaffRoleDeletedEvent } from '../../../events/types/staff-role-deleted.ts'; import type { Passport } from '../../passport.ts'; -import { StaffRole, type StaffRoleEntityReference, type StaffRoleProps } from './staff-role.ts'; +import { StaffRole, type StaffRoleProps } from './staff-role.ts'; import { StaffRolePermissions } from './staff-role-permissions.ts'; const test = { for: describeFeature }; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const feature = await loadFeature(path.resolve(__dirname, 'features/staff-role.feature')); -function makePassport(canManageStaffRolesAndPermissions = true, isSystemAccount = false): Passport { +function makePassport(canManageStaffRolesAndPermissions = true, isSystemAccount = false, canRemoveRole = false): Passport { return vi.mocked({ user: { forStaffRole: vi.fn(() => ({ - determineIf: (fn: (p: { canManageStaffRolesAndPermissions: boolean; isSystemAccount: boolean }) => boolean) => fn({ canManageStaffRolesAndPermissions, isSystemAccount }), + determineIf: (fn: (p: { canManageStaffRolesAndPermissions: boolean; isSystemAccount: boolean; canRemoveRole: boolean }) => boolean) => fn({ canManageStaffRolesAndPermissions, isSystemAccount, canRemoveRole }), })), }, } as unknown as Passport); @@ -197,50 +197,46 @@ test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { }); }); - // deleteAndReassignTo - Scenario('Deleting a non-default staff role with permission', ({ Given, When, Then, And }) => { + // requestDelete + Scenario('Deleting a non-default staff role with the remove-role permission', ({ Given, When, Then, And }) => { let deletedRole: StaffRole; - Given('a StaffRole aggregate that is not deleted and is not default, with permission to manage staff roles and permissions', () => { - passport = makePassport(true, false); - deletedRole = new StaffRole(makeBaseProps({ isDefault: false }), passport); + Given('a StaffRole aggregate that is not deleted and is not default, with permission to remove staff roles', () => { + passport = makePassport(false, false, true); + deletedRole = new StaffRole(makeBaseProps({ isDefault: false, enterpriseAppRole: 'Staff.CaseManager' }), passport); }); - When('I call deleteAndReassignTo with a valid StaffRoleEntityReference', () => { - deletedRole.deleteAndReassignTo({ - id: 'role-2', - } as StaffRoleEntityReference); + When('I call requestDelete', () => { + deletedRole.requestDelete(); }); Then('the staff role should be marked as deleted', () => { expect(deletedRole.isDeleted).toBe(true); }); - And('a RoleDeletedReassignEvent should be added to integration events', () => { - const event = getIntegrationEvent(deletedRole.getIntegrationEvents(), RoleDeletedReassignEvent); + And('a StaffRoleDeletedEvent should be added to integration events', () => { + const event = getIntegrationEvent(deletedRole.getIntegrationEvents(), StaffRoleDeletedEvent); expect(event).toBeDefined(); - expect(event).toBeInstanceOf(RoleDeletedReassignEvent); + expect(event).toBeInstanceOf(StaffRoleDeletedEvent); expect(event?.payload.deletedRoleId).toBe('role-1'); - expect(event?.payload.newRoleId).toBe('role-2'); + expect(event?.payload.enterpriseAppRole).toBe('Staff.CaseManager'); }); }); - Scenario('Deleting a non-default staff role without permission', ({ Given, When, Then, And }) => { + Scenario('Deleting a non-default staff role without the remove-role permission', ({ Given, When, Then, And }) => { let deletedRole: StaffRole; let deletingRoleWithoutPermission: () => void; - Given('a StaffRole aggregate that is not deleted and is not default, without permission to manage staff roles and permissions', () => { - passport = makePassport(false, false); + Given('a StaffRole aggregate that is not deleted and is not default, without permission to remove staff roles', () => { + passport = makePassport(true, false, false); deletedRole = new StaffRole(makeBaseProps({ isDefault: false }), passport); }); - When('I try to call deleteAndReassignTo with a valid StaffRoleEntityReference', () => { + When('I try to call requestDelete', () => { deletingRoleWithoutPermission = () => { - deletedRole.deleteAndReassignTo({ - id: 'role-2', - } as StaffRoleEntityReference); + deletedRole.requestDelete(); }; }); Then('a PermissionError should be thrown', () => { expect(deletingRoleWithoutPermission).toThrow(PermissionError); expect(deletingRoleWithoutPermission).toThrow('You do not have permission to delete this role'); }); - And('no RoleDeletedReassignEvent should be emitted', () => { - const event = getIntegrationEvent(deletedRole.getIntegrationEvents(), RoleDeletedReassignEvent); + And('no StaffRoleDeletedEvent should be emitted', () => { + const event = getIntegrationEvent(deletedRole.getIntegrationEvents(), StaffRoleDeletedEvent); expect(event).toBeUndefined(); }); }); @@ -249,21 +245,38 @@ test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { let defaultRole: StaffRole; let deletingDefaultRole: () => void; Given('a StaffRole aggregate that is default', () => { - passport = makePassport(true, false); + passport = makePassport(true, false, true); defaultRole = new StaffRole(makeBaseProps({ isDefault: true }), passport); }); - When('I try to call deleteAndReassignTo with a valid StaffRoleEntityReference', () => { + When('I try to call requestDelete', () => { deletingDefaultRole = () => { - defaultRole.deleteAndReassignTo({ - id: 'role-2', - } as StaffRoleEntityReference); + defaultRole.requestDelete(); }; }); Then('a PermissionError should be thrown', () => { expect(deletingDefaultRole).toThrow(PermissionError); + expect(deletingDefaultRole).toThrow('You cannot delete a default staff role'); }); - And('no RoleDeletedReassignEvent should be emitted', () => { - const event = getIntegrationEvent(defaultRole.getIntegrationEvents(), RoleDeletedReassignEvent); + And('no StaffRoleDeletedEvent should be emitted', () => { + const event = getIntegrationEvent(defaultRole.getIntegrationEvents(), StaffRoleDeletedEvent); + expect(event).toBeUndefined(); + }); + }); + + Scenario('Deleting an already deleted staff role is idempotent', ({ Given, When, Then }) => { + let deletedRole: StaffRole; + Given('a StaffRole aggregate that is already deleted, with permission to remove staff roles', () => { + passport = makePassport(false, false, true); + deletedRole = new StaffRole(makeBaseProps({ isDefault: false }), passport); + deletedRole.requestDelete(); + deletedRole.clearIntegrationEvents(); + }); + When('I call requestDelete again', () => { + deletedRole.requestDelete(); + }); + Then('no additional StaffRoleDeletedEvent should be emitted', () => { + expect(deletedRole.isDeleted).toBe(true); + const event = getIntegrationEvent(deletedRole.getIntegrationEvents(), StaffRoleDeletedEvent); expect(event).toBeUndefined(); }); }); @@ -515,4 +528,54 @@ test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { expect(role.permissions.userPermissions.canManageUsers).toBe(true); }); }); + + Scenario('Getting default role names', ({ When, Then, And }) => { + let names: string[]; + When('I call getDefaultRoleNames', () => { + names = StaffRole.getDefaultRoleNames(); + }); + Then('the result should contain "Default.CaseManager"', () => { + expect(names).toContain('Default.CaseManager'); + }); + And('the result should contain "Default.ServiceLineOwner"', () => { + expect(names).toContain('Default.ServiceLineOwner'); + }); + And('the result should contain "Default.Finance"', () => { + expect(names).toContain('Default.Finance'); + }); + And('the result should contain "Default.TechAdmin"', () => { + expect(names).toContain('Default.TechAdmin'); + }); + And('the result should have exactly 4 names', () => { + expect(names).toHaveLength(4); + }); + }); + + Scenario('Creating a default tech admin role', ({ When, Then, And }) => { + let role: StaffRole; + When('I create a default tech admin staff role', () => { + role = StaffRole.getNewDefaultTechAdminInstance(makeFactoryProps(), makePassport(true, true)); + }); + Then('the roleName should be "Default Tech Admin"', () => { + expect(role.roleName).toBe('Default Tech Admin'); + }); + And('the enterpriseAppRole should be "Staff.TechAdmin"', () => { + expect(role.enterpriseAppRole).toBe('Staff.TechAdmin'); + }); + And('the tech admin role should allow managing communities', () => { + expect(role.permissions.communityPermissions.canManageCommunities).toBe(true); + }); + And('the tech admin role should allow managing staff roles and permissions', () => { + expect(role.permissions.communityPermissions.canManageStaffRolesAndPermissions).toBe(true); + }); + And('the tech admin role should allow managing finance', () => { + expect(role.permissions.financePermissions.canManageFinance).toBe(true); + }); + And('the tech admin role should allow managing tech admin', () => { + expect(role.permissions.techAdminPermissions.canManageTechAdmin).toBe(true); + }); + And('the tech admin role should allow managing users', () => { + expect(role.permissions.userPermissions.canManageUsers).toBe(true); + }); + }); }); diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.ts index 1bec5d72e..098ce000e 100644 --- a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.ts +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.ts @@ -1,7 +1,7 @@ import { AggregateRoot } from '@cellix/domain-seedwork/aggregate-root'; import type { DomainEntityProps } from '@cellix/domain-seedwork/domain-entity'; import { PermissionError } from '@cellix/domain-seedwork/domain-entity'; -import { RoleDeletedReassignEvent, type RoleDeletedReassignProps } from '../../../events/types/role-deleted-reassign.ts'; +import { StaffRoleDeletedEvent, type StaffRoleDeletedProps } from '../../../events/types/staff-role-deleted.ts'; import type { Passport } from '../../passport.ts'; import type { UserVisa } from '../user.visa.ts'; import * as ValueObjects from './staff-role.value-objects.ts'; @@ -125,17 +125,28 @@ export class StaffRole extends AggregateRoot permissions.canManageStaffRolesAndPermissions)) { + if (!this.isDeleted && !this.visa.determineIf((permissions) => permissions.canRemoveRole || permissions.isSystemAccount)) { throw new PermissionError('You do not have permission to delete this role'); } + if (this.isDeleted) { + return; + } super.isDeleted = true; - this.addIntegrationEvent(RoleDeletedReassignEvent, { + this.addIntegrationEvent(StaffRoleDeletedEvent, { deletedRoleId: this.props.id, - newRoleId: roleRef.id, + enterpriseAppRole: this.props.enterpriseAppRole, }); } diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-user/staff-user-activity-log.entity.additional.test.ts b/packages/ocom/domain/src/domain/contexts/user/staff-user/staff-user-activity-log.entity.additional.test.ts index 3ba3da8f0..9291b4a5c 100644 --- a/packages/ocom/domain/src/domain/contexts/user/staff-user/staff-user-activity-log.entity.additional.test.ts +++ b/packages/ocom/domain/src/domain/contexts/user/staff-user/staff-user-activity-log.entity.additional.test.ts @@ -10,6 +10,7 @@ function createVisa(isSystemAccount: boolean, canManageStaffRolesAndPermissions func({ canManageEndUsers: false, canManageStaffRolesAndPermissions, + canRemoveRole: false, canManageStaffUsers: false, canManageVendorUsers: false, isEditingOwnAccount: false, diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-user/staff-user.repository.ts b/packages/ocom/domain/src/domain/contexts/user/staff-user/staff-user.repository.ts index d3bd56421..a2faddd99 100644 --- a/packages/ocom/domain/src/domain/contexts/user/staff-user/staff-user.repository.ts +++ b/packages/ocom/domain/src/domain/contexts/user/staff-user/staff-user.repository.ts @@ -3,5 +3,6 @@ import type { StaffUser, StaffUserProps } from './staff-user.ts'; export interface StaffUserRepository extends Repository> { delete(id: string): Promise; getByExternalId(externalId: string): Promise>; + getAllAssignedToRole(roleId: string): Promise[]>; getNewInstance(externalId: string, firstName: string, lastName: string, email: string): Promise>; } diff --git a/packages/ocom/domain/src/domain/contexts/user/user.domain-permissions.ts b/packages/ocom/domain/src/domain/contexts/user/user.domain-permissions.ts index a8521c146..6946d6ac0 100644 --- a/packages/ocom/domain/src/domain/contexts/user/user.domain-permissions.ts +++ b/packages/ocom/domain/src/domain/contexts/user/user.domain-permissions.ts @@ -4,6 +4,7 @@ export interface UserDomainPermissions { //StaffRole Aggregate Root canManageStaffRolesAndPermissions: boolean; + canRemoveRole: boolean; //StaffUser Aggregate Root canManageStaffUsers: boolean; diff --git a/packages/ocom/domain/src/domain/events/types/index.ts b/packages/ocom/domain/src/domain/events/types/index.ts index d28b84368..9df561655 100644 --- a/packages/ocom/domain/src/domain/events/types/index.ts +++ b/packages/ocom/domain/src/domain/events/types/index.ts @@ -3,3 +3,4 @@ export { MemberActivatedEvent } from './member-activated.ts'; export { MemberDeactivatedEvent } from './member-deactivated.ts'; export { MemberInvitedEvent } from './member-invited.ts'; export { MemberRemovedEvent } from './member-removed.ts'; +export { StaffRoleDeletedEvent } from './staff-role-deleted.ts'; diff --git a/packages/ocom/domain/src/domain/events/types/staff-role-deleted.ts b/packages/ocom/domain/src/domain/events/types/staff-role-deleted.ts new file mode 100644 index 000000000..ccb4e5b65 --- /dev/null +++ b/packages/ocom/domain/src/domain/events/types/staff-role-deleted.ts @@ -0,0 +1,13 @@ +import { CustomDomainEventImpl } from '@cellix/domain-seedwork/domain-event'; + +export interface StaffRoleDeletedProps { + deletedRoleId: string; + /** + * Enterprise app role of the deleted staff role. Carried on the payload + * because the staff role document is hard-deleted when the deletion + * commits, so handlers can no longer read it from the repository. + */ + enterpriseAppRole: string; +} + +export class StaffRoleDeletedEvent extends CustomDomainEventImpl {} diff --git a/packages/ocom/domain/src/domain/iam/member/contexts/member.user.end-user.visa.ts b/packages/ocom/domain/src/domain/iam/member/contexts/member.user.end-user.visa.ts index 29ec97f0e..bcc78a9e0 100644 --- a/packages/ocom/domain/src/domain/iam/member/contexts/member.user.end-user.visa.ts +++ b/packages/ocom/domain/src/domain/iam/member/contexts/member.user.end-user.visa.ts @@ -16,6 +16,7 @@ export class MemberUserEndUserVisa implemen const updatedPermissions: UserDomainPermissions = { canManageEndUsers: false, canManageStaffRolesAndPermissions: false, + canRemoveRole: false, canManageStaffUsers: false, canManageVendorUsers: false, isEditingOwnAccount: this.member.accounts.some((account) => account.user.id === this.root.id), diff --git a/packages/ocom/domain/src/domain/iam/member/contexts/member.user.staff-role.visa.ts b/packages/ocom/domain/src/domain/iam/member/contexts/member.user.staff-role.visa.ts index acce8a495..c28d7f3d8 100644 --- a/packages/ocom/domain/src/domain/iam/member/contexts/member.user.staff-role.visa.ts +++ b/packages/ocom/domain/src/domain/iam/member/contexts/member.user.staff-role.visa.ts @@ -15,6 +15,7 @@ export class MemberUserStaffRoleVisa impl const updatedPermissions: UserDomainPermissions = { canManageEndUsers: false, canManageStaffRolesAndPermissions: false, + canRemoveRole: false, canManageStaffUsers: false, canManageVendorUsers: false, isEditingOwnAccount: false, diff --git a/packages/ocom/domain/src/domain/iam/member/contexts/member.user.staff-user.visa.ts b/packages/ocom/domain/src/domain/iam/member/contexts/member.user.staff-user.visa.ts index 653c0d362..645690fc6 100644 --- a/packages/ocom/domain/src/domain/iam/member/contexts/member.user.staff-user.visa.ts +++ b/packages/ocom/domain/src/domain/iam/member/contexts/member.user.staff-user.visa.ts @@ -15,6 +15,7 @@ export class MemberUserStaffUserVisa impl const updatedPermissions: UserDomainPermissions = { canManageEndUsers: false, canManageStaffRolesAndPermissions: false, + canRemoveRole: false, canManageStaffUsers: false, canManageVendorUsers: false, isEditingOwnAccount: false, diff --git a/packages/ocom/domain/src/domain/iam/member/contexts/member.user.vendor-user.visa.ts b/packages/ocom/domain/src/domain/iam/member/contexts/member.user.vendor-user.visa.ts index b57a60253..5c70b1d3b 100644 --- a/packages/ocom/domain/src/domain/iam/member/contexts/member.user.vendor-user.visa.ts +++ b/packages/ocom/domain/src/domain/iam/member/contexts/member.user.vendor-user.visa.ts @@ -15,6 +15,7 @@ export class MemberUserVendorUserVisa im const updatedPermissions: UserDomainPermissions = { canManageEndUsers: false, canManageStaffRolesAndPermissions: false, + canRemoveRole: false, canManageStaffUsers: false, canManageVendorUsers: false, isEditingOwnAccount: false, diff --git a/packages/ocom/domain/src/domain/iam/user/staff-user/contexts/features/staff-user.user.passport.feature b/packages/ocom/domain/src/domain/iam/user/staff-user/contexts/features/staff-user.user.passport.feature index 47e2d8262..cbee0fbe3 100644 --- a/packages/ocom/domain/src/domain/iam/user/staff-user/contexts/features/staff-user.user.passport.feature +++ b/packages/ocom/domain/src/domain/iam/user/staff-user/contexts/features/staff-user.user.passport.feature @@ -40,6 +40,16 @@ Feature: StaffUserUserPassport Then determineIf should return true for canManageStaffRolesAndPermissions And determineIf should return false for isEditingOwnAccount + Scenario: forStaffRole maps canRemoveRole from the staff user's role permissions + Given a StaffUserUserPassport for a staff user whose role grants canRemoveRole + When I call forStaffRole with any StaffRoleEntityReference + Then determineIf should return true for canRemoveRole + + Scenario: forStaffRole denies canRemoveRole when the staff user's role does not grant it + Given a StaffUserUserPassport for a staff user whose role does not grant canRemoveRole + When I call forStaffRole with any StaffRoleEntityReference + Then determineIf should return false for canRemoveRole + Scenario: forVendorUser returns a visa where canManageStaffRolesAndPermissions is true Given a StaffUserUserPassport for the staff user When I call forVendorUser with any VendorUserEntityReference diff --git a/packages/ocom/domain/src/domain/iam/user/staff-user/contexts/staff-user.user.passport.test.ts b/packages/ocom/domain/src/domain/iam/user/staff-user/contexts/staff-user.user.passport.test.ts index 7c67ea067..8428c0e69 100644 --- a/packages/ocom/domain/src/domain/iam/user/staff-user/contexts/staff-user.user.passport.test.ts +++ b/packages/ocom/domain/src/domain/iam/user/staff-user/contexts/staff-user.user.passport.test.ts @@ -14,7 +14,7 @@ const feature = await loadFeature(path.resolve(__dirname, 'features/staff-user.u // ─── Helpers ───────────────────────────────────────────────────────────────── -function makeStaffUser(externalId = 'ext-1', canManageStaffRolesAndPermissions = true): StaffUserEntityReference { +function makeStaffUser(externalId = 'ext-1', canManageStaffRolesAndPermissions = true, canRemoveRole = false): StaffUserEntityReference { return { id: 'staff-1', externalId, @@ -23,6 +23,9 @@ function makeStaffUser(externalId = 'ext-1', canManageStaffRolesAndPermissions = communityPermissions: { canManageStaffRolesAndPermissions, }, + staffRolePermissions: { + canRemoveRole, + }, }, }, } as unknown as StaffUserEntityReference; @@ -156,6 +159,32 @@ test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { }); }); + Scenario("forStaffRole maps canRemoveRole from the staff user's role permissions", ({ Given, When, Then }) => { + let visa: ReturnType; + Given('a StaffUserUserPassport for a staff user whose role grants canRemoveRole', () => { + passport = new StaffUserUserPassport(makeStaffUser('ext-1', true, true)); + }); + When('I call forStaffRole with any StaffRoleEntityReference', () => { + visa = passport.forStaffRole({} as StaffRoleEntityReference); + }); + Then('determineIf should return true for canRemoveRole', () => { + expect(visa.determineIf((p) => p.canRemoveRole)).toBe(true); + }); + }); + + Scenario("forStaffRole denies canRemoveRole when the staff user's role does not grant it", ({ Given, When, Then }) => { + let visa: ReturnType; + Given('a StaffUserUserPassport for a staff user whose role does not grant canRemoveRole', () => { + passport = new StaffUserUserPassport(makeStaffUser('ext-1', true, false)); + }); + When('I call forStaffRole with any StaffRoleEntityReference', () => { + visa = passport.forStaffRole({} as StaffRoleEntityReference); + }); + Then('determineIf should return false for canRemoveRole', () => { + expect(visa.determineIf((p) => p.canRemoveRole)).toBe(false); + }); + }); + // ─── forVendorUser ──────────────────────────────────────────────────────── Scenario('forVendorUser returns a visa where canManageStaffRolesAndPermissions is true', ({ Given, When, Then, And }) => { diff --git a/packages/ocom/domain/src/domain/iam/user/staff-user/contexts/staff-user.user.passport.ts b/packages/ocom/domain/src/domain/iam/user/staff-user/contexts/staff-user.user.passport.ts index 7375b9941..2deb49883 100644 --- a/packages/ocom/domain/src/domain/iam/user/staff-user/contexts/staff-user.user.passport.ts +++ b/packages/ocom/domain/src/domain/iam/user/staff-user/contexts/staff-user.user.passport.ts @@ -33,6 +33,7 @@ export class StaffUserUserPassport extends StaffUserPassportBase implements User return { canManageEndUsers: false, canManageStaffRolesAndPermissions, + canRemoveRole: this._user.role?.permissions.staffRolePermissions.canRemoveRole ?? false, canManageStaffUsers: canManageStaffRolesAndPermissions, canManageVendorUsers: false, isEditingOwnAccount: root !== undefined && root.externalId === this._user.externalId, diff --git a/packages/ocom/domain/src/domain/services/features/index.feature b/packages/ocom/domain/src/domain/services/features/index.feature index f6f802cad..f9c30d8a5 100644 --- a/packages/ocom/domain/src/domain/services/features/index.feature +++ b/packages/ocom/domain/src/domain/services/features/index.feature @@ -3,4 +3,9 @@ Feature: Services Index Scenario: Exporting Community services Given the services index module When I import the Community export - Then it should export the Community services object \ No newline at end of file + Then it should export the Community services object + + Scenario: Exporting User services + Given the services index module + When I import the User export + Then it should export the User services object \ No newline at end of file diff --git a/packages/ocom/domain/src/domain/services/index.test.ts b/packages/ocom/domain/src/domain/services/index.test.ts index 0b81fe9fb..26a8ebc0a 100644 --- a/packages/ocom/domain/src/domain/services/index.test.ts +++ b/packages/ocom/domain/src/domain/services/index.test.ts @@ -2,7 +2,7 @@ import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { describeFeature, loadFeature } from '@amiceli/vitest-cucumber'; import { expect } from 'vitest'; -import { Community } from './index.ts'; +import { Community, User } from './index.ts'; const test = { for: describeFeature }; const __dirname = path.dirname(fileURLToPath(import.meta.url)); @@ -25,4 +25,20 @@ test.for(feature, ({ Scenario }) => { expect(typeof communityExport).toBe('object'); }); }); + + Scenario('Exporting User services', ({ Given, When, Then }) => { + let userExport: typeof User; + Given('the services index module', () => { + // Module is already imported + }); + + When('I import the User export', () => { + userExport = User; + }); + + Then('it should export the User services object', () => { + expect(userExport).toBeDefined(); + expect(typeof userExport).toBe('object'); + }); + }); }); diff --git a/packages/ocom/domain/src/domain/services/index.ts b/packages/ocom/domain/src/domain/services/index.ts index d8d17c1ba..97b509231 100644 --- a/packages/ocom/domain/src/domain/services/index.ts +++ b/packages/ocom/domain/src/domain/services/index.ts @@ -1 +1,2 @@ export { Community } from './community/index.ts'; +export { User } from './user/index.ts'; diff --git a/packages/ocom/domain/src/domain/services/user/features/index.feature b/packages/ocom/domain/src/domain/services/user/features/index.feature new file mode 100644 index 000000000..51283ca70 --- /dev/null +++ b/packages/ocom/domain/src/domain/services/user/features/index.feature @@ -0,0 +1,6 @@ +Feature: User Services Index + + Scenario: Exporting StaffRoleDeletedReassignmentService + Given the user services index module + When I import the User export + Then it should expose a StaffRoleDeletedReassignmentService instance diff --git a/packages/ocom/domain/src/domain/services/user/features/staff-role-deleted-reassignment.service.feature b/packages/ocom/domain/src/domain/services/user/features/staff-role-deleted-reassignment.service.feature new file mode 100644 index 000000000..c8f147a85 --- /dev/null +++ b/packages/ocom/domain/src/domain/services/user/features/staff-role-deleted-reassignment.service.feature @@ -0,0 +1,29 @@ +Feature: StaffRoleDeletedReassignmentService + + Background: + Given a StaffRoleDeletedReassignmentService instance + And a valid domainDataSource with staff role and staff user repositories + And a default staff role with id "default-role-1" and enterpriseAppRole "Staff.CaseManager" + + Scenario: Reassigning staff users assigned to the deleted role to the matching default role + Given two staff users assigned to the deleted role "deleted-role-1" + When I call reassignStaffUsersToDefaultRole for role "deleted-role-1" with enterpriseAppRole "Staff.CaseManager" + Then each assigned staff user should be reassigned to the default role "default-role-1" + And each reassigned staff user should be saved + + Scenario: Reassignment is idempotent for staff users already assigned to the default role + Given a staff user already assigned to the default role "default-role-1" + When I call reassignStaffUsersToDefaultRole for role "deleted-role-1" with enterpriseAppRole "Staff.CaseManager" + Then that staff user should not be reassigned again + And no staff user should be saved + + Scenario: No staff users are assigned to the deleted role + Given no staff users assigned to the deleted role "deleted-role-1" + When I call reassignStaffUsersToDefaultRole for role "deleted-role-1" with enterpriseAppRole "Staff.CaseManager" + Then no staff user should be saved + + Scenario: Failing when no default role matches the deleted role's enterpriseAppRole + Given no default staff role exists for enterpriseAppRole "Staff.Unmatched" + When I try to call reassignStaffUsersToDefaultRole for role "deleted-role-1" with enterpriseAppRole "Staff.Unmatched" + Then the missing default role failure should be logged and rethrown + And no staff user should be saved diff --git a/packages/ocom/domain/src/domain/services/user/index.test.ts b/packages/ocom/domain/src/domain/services/user/index.test.ts new file mode 100644 index 000000000..97040c714 --- /dev/null +++ b/packages/ocom/domain/src/domain/services/user/index.test.ts @@ -0,0 +1,29 @@ +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { describeFeature, loadFeature } from '@amiceli/vitest-cucumber'; +import { expect } from 'vitest'; +import { User } from './index.ts'; +import { StaffRoleDeletedReassignmentService } from './staff-role-deleted-reassignment.service.ts'; + +const test = { for: describeFeature }; +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const feature = await loadFeature(path.resolve(__dirname, 'features/index.feature')); + +test.for(feature, ({ Scenario }) => { + let userExport: typeof User; + + Scenario('Exporting StaffRoleDeletedReassignmentService', ({ Given, When, Then }) => { + Given('the user services index module', () => { + // Module is already imported + }); + + When('I import the User export', () => { + userExport = User; + }); + + Then('it should expose a StaffRoleDeletedReassignmentService instance', () => { + expect(userExport).toBeDefined(); + expect(userExport.StaffRoleDeletedReassignmentService).toBeInstanceOf(StaffRoleDeletedReassignmentService); + }); + }); +}); diff --git a/packages/ocom/domain/src/domain/services/user/index.ts b/packages/ocom/domain/src/domain/services/user/index.ts new file mode 100644 index 000000000..a7662c3f3 --- /dev/null +++ b/packages/ocom/domain/src/domain/services/user/index.ts @@ -0,0 +1,5 @@ +import { StaffRoleDeletedReassignmentService } from './staff-role-deleted-reassignment.service.ts'; + +export const User = { + StaffRoleDeletedReassignmentService: new StaffRoleDeletedReassignmentService(), +}; diff --git a/packages/ocom/domain/src/domain/services/user/staff-role-deleted-reassignment.service.test.ts b/packages/ocom/domain/src/domain/services/user/staff-role-deleted-reassignment.service.test.ts new file mode 100644 index 000000000..8c6da6af7 --- /dev/null +++ b/packages/ocom/domain/src/domain/services/user/staff-role-deleted-reassignment.service.test.ts @@ -0,0 +1,177 @@ +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { describeFeature, loadFeature } from '@amiceli/vitest-cucumber'; +import { expect, type MockedFunction, vi } from 'vitest'; +import type { DomainDataSource } from '../../../index.ts'; +import type { Passport } from '../../contexts/passport.ts'; +import type * as StaffRole from '../../contexts/user/staff-role/index.ts'; +import { StaffRoleDeletedReassignmentService } from './staff-role-deleted-reassignment.service.ts'; + +const test = { for: describeFeature }; +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const feature = await loadFeature(path.resolve(__dirname, 'features/staff-role-deleted-reassignment.service.feature')); + +interface MockStaffUser { + id: string; + role: { id: string } | undefined; + requestRoleAssignment: MockedFunction<(role: StaffRole.StaffRoleEntityReference, description: string, activityByStaffUserId: string) => void>; +} + +function makeMockStaffUser(id: string, roleId: string | undefined): MockStaffUser { + return { + id, + role: roleId ? { id: roleId } : undefined, + requestRoleAssignment: vi.fn(), + }; +} + +test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { + let service: StaffRoleDeletedReassignmentService; + let mockDomainDataSource: DomainDataSource; + let mockDefaultRole: StaffRole.StaffRoleEntityReference; + let mockStaffRoleRepo: { + getDefaultRoleByEnterpriseAppRole: MockedFunction<(enterpriseAppRole: string) => Promise>; + }; + let mockStaffUserRepo: { + getAllAssignedToRole: MockedFunction<(roleId: string) => Promise>; + save: MockedFunction<(staffUser: MockStaffUser) => Promise>; + }; + let assignedStaffUsers: MockStaffUser[]; + let capturedPassport: Passport | undefined; + let thrownError: Error | null = null; + let consoleErrorSpy: ReturnType; + + BeforeEachScenario(() => { + thrownError = null; + capturedPassport = undefined; + assignedStaffUsers = []; + consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => undefined); + + mockDefaultRole = { + id: 'default-role-1', + roleName: 'Default Case Manager', + enterpriseAppRole: 'Staff.CaseManager', + isDefault: true, + } as unknown as StaffRole.StaffRoleEntityReference; + + mockStaffRoleRepo = { + getDefaultRoleByEnterpriseAppRole: vi.fn(), + }; + mockStaffUserRepo = { + getAllAssignedToRole: vi.fn(async () => assignedStaffUsers), + save: vi.fn(async (staffUser: MockStaffUser) => staffUser), + }; + mockStaffRoleRepo.getDefaultRoleByEnterpriseAppRole.mockImplementation((enterpriseAppRole: string) => { + if (enterpriseAppRole === mockDefaultRole.enterpriseAppRole) { + return Promise.resolve(mockDefaultRole); + } + return Promise.reject(new Error(`StaffRole with enterpriseAppRole ${enterpriseAppRole} not found`)); + }); + + mockDomainDataSource = { + User: { + StaffRole: { + StaffRoleUnitOfWork: { + withTransaction: vi.fn(), + withScopedTransaction: vi.fn(async (fn: (repo: typeof mockStaffRoleRepo) => Promise) => { + await fn(mockStaffRoleRepo); + }), + }, + }, + StaffUser: { + StaffUserUnitOfWork: { + withTransaction: vi.fn(async (passport: Passport, fn: (repo: typeof mockStaffUserRepo) => Promise) => { + capturedPassport = passport; + await fn(mockStaffUserRepo); + }), + withScopedTransaction: vi.fn(), + }, + }, + }, + } as unknown as DomainDataSource; + + service = new StaffRoleDeletedReassignmentService(); + }); + + Background(({ Given, And }) => { + Given('a StaffRoleDeletedReassignmentService instance', () => { + // Created in BeforeEachScenario + }); + And('a valid domainDataSource with staff role and staff user repositories', () => { + // Created in BeforeEachScenario + }); + And('a default staff role with id "default-role-1" and enterpriseAppRole "Staff.CaseManager"', () => { + // Created in BeforeEachScenario + }); + }); + + Scenario('Reassigning staff users assigned to the deleted role to the matching default role', ({ Given, When, Then, And }) => { + Given('two staff users assigned to the deleted role "deleted-role-1"', () => { + assignedStaffUsers = [makeMockStaffUser('staff-user-1', 'deleted-role-1'), makeMockStaffUser('staff-user-2', 'deleted-role-1')]; + }); + When('I call reassignStaffUsersToDefaultRole for role "deleted-role-1" with enterpriseAppRole "Staff.CaseManager"', async () => { + await service.reassignStaffUsersToDefaultRole('deleted-role-1', 'Staff.CaseManager', mockDomainDataSource); + }); + Then('each assigned staff user should be reassigned to the default role "default-role-1"', () => { + expect(mockStaffUserRepo.getAllAssignedToRole).toHaveBeenCalledWith('deleted-role-1'); + for (const staffUser of assignedStaffUsers) { + expect(staffUser.requestRoleAssignment).toHaveBeenCalledTimes(1); + expect(staffUser.requestRoleAssignment).toHaveBeenCalledWith(mockDefaultRole, expect.stringContaining('Default Case Manager'), staffUser.id); + } + expect(capturedPassport).toBeDefined(); + }); + And('each reassigned staff user should be saved', () => { + expect(mockStaffUserRepo.save).toHaveBeenCalledTimes(2); + expect(mockStaffUserRepo.save).toHaveBeenCalledWith(assignedStaffUsers[0]); + expect(mockStaffUserRepo.save).toHaveBeenCalledWith(assignedStaffUsers[1]); + }); + }); + + Scenario('Reassignment is idempotent for staff users already assigned to the default role', ({ Given, When, Then, And }) => { + Given('a staff user already assigned to the default role "default-role-1"', () => { + assignedStaffUsers = [makeMockStaffUser('staff-user-1', 'default-role-1')]; + }); + When('I call reassignStaffUsersToDefaultRole for role "deleted-role-1" with enterpriseAppRole "Staff.CaseManager"', async () => { + await service.reassignStaffUsersToDefaultRole('deleted-role-1', 'Staff.CaseManager', mockDomainDataSource); + }); + Then('that staff user should not be reassigned again', () => { + expect(assignedStaffUsers[0]?.requestRoleAssignment).not.toHaveBeenCalled(); + }); + And('no staff user should be saved', () => { + expect(mockStaffUserRepo.save).not.toHaveBeenCalled(); + }); + }); + + Scenario('No staff users are assigned to the deleted role', ({ Given, When, Then }) => { + Given('no staff users assigned to the deleted role "deleted-role-1"', () => { + assignedStaffUsers = []; + }); + When('I call reassignStaffUsersToDefaultRole for role "deleted-role-1" with enterpriseAppRole "Staff.CaseManager"', async () => { + await service.reassignStaffUsersToDefaultRole('deleted-role-1', 'Staff.CaseManager', mockDomainDataSource); + }); + Then('no staff user should be saved', () => { + expect(mockStaffUserRepo.save).not.toHaveBeenCalled(); + }); + }); + + Scenario("Failing when no default role matches the deleted role's enterpriseAppRole", ({ Given, When, Then, And }) => { + Given('no default staff role exists for enterpriseAppRole "Staff.Unmatched"', () => { + assignedStaffUsers = [makeMockStaffUser('staff-user-1', 'deleted-role-1')]; + }); + When('I try to call reassignStaffUsersToDefaultRole for role "deleted-role-1" with enterpriseAppRole "Staff.Unmatched"', async () => { + try { + await service.reassignStaffUsersToDefaultRole('deleted-role-1', 'Staff.Unmatched', mockDomainDataSource); + } catch (error) { + thrownError = error as Error; + } + }); + Then('the missing default role failure should be logged and rethrown', () => { + expect(thrownError).not.toBeNull(); + expect(thrownError?.message).toContain('Staff.Unmatched'); + expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining('Staff.Unmatched'), expect.any(Error)); + }); + And('no staff user should be saved', () => { + expect(mockStaffUserRepo.save).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/packages/ocom/domain/src/domain/services/user/staff-role-deleted-reassignment.service.ts b/packages/ocom/domain/src/domain/services/user/staff-role-deleted-reassignment.service.ts new file mode 100644 index 000000000..1b1923050 --- /dev/null +++ b/packages/ocom/domain/src/domain/services/user/staff-role-deleted-reassignment.service.ts @@ -0,0 +1,48 @@ +import type { DomainDataSource } from '../../../index.ts'; +import { PassportFactory } from '../../contexts/passport.ts'; +import type * as StaffRole from '../../contexts/user/staff-role/index.ts'; + +export class StaffRoleDeletedReassignmentService { + /** + * Reassigns every staff user assigned to a deleted staff role to the + * default staff role whose enterpriseAppRole matches the deleted role's. + * + * Idempotent: staff users already assigned to the matching default role + * are skipped, so re-processing the same event causes no changes. + * + * @throws when no default staff role matches the deleted role's + * enterpriseAppRole — the failure is logged and rethrown so the event is + * observed as a processing failure instead of silently stranding users. + */ + async reassignStaffUsersToDefaultRole(deletedRoleId: string, enterpriseAppRole: string, domainDataSource: DomainDataSource): Promise { + let defaultRole: StaffRole.StaffRoleEntityReference | null = null; + try { + await domainDataSource.User.StaffRole.StaffRoleUnitOfWork.withScopedTransaction(async (repo) => { + defaultRole = await repo.getDefaultRoleByEnterpriseAppRole(enterpriseAppRole); + }); + } catch (error) { + console.error(`No default staff role found for enterprise app role "${enterpriseAppRole}" while reassigning staff users from deleted role ${deletedRoleId}`, error); + throw error; + } + if (!defaultRole) { + const message = `No default staff role found for enterprise app role "${enterpriseAppRole}" while reassigning staff users from deleted role ${deletedRoleId}`; + console.error(message); + throw new Error(message); + } + const matchingDefaultRole = defaultRole as StaffRole.StaffRoleEntityReference; + + const systemPassport = PassportFactory.forSystem({ + canManageStaffRolesAndPermissions: true, + }); + await domainDataSource.User.StaffUser.StaffUserUnitOfWork.withTransaction(systemPassport, async (repo) => { + const assignedStaffUsers = await repo.getAllAssignedToRole(deletedRoleId); + for (const staffUser of assignedStaffUsers) { + if (staffUser.role?.id === matchingDefaultRole.id) { + continue; + } + staffUser.requestRoleAssignment(matchingDefaultRole, `Reassigned to default role ${matchingDefaultRole.roleName} after previous role was deleted`, staffUser.id); + await repo.save(staffUser); + } + }); + } +} diff --git a/packages/ocom/event-handler/src/handlers/integration/index.ts b/packages/ocom/event-handler/src/handlers/integration/index.ts index a2065b65a..b9dc34636 100644 --- a/packages/ocom/event-handler/src/handlers/integration/index.ts +++ b/packages/ocom/event-handler/src/handlers/integration/index.ts @@ -1,6 +1,8 @@ import type { DomainDataSource } from '@ocom/domain'; import RegisterCommunityCreatedProvisionMemberAndDefaultRoleHandler from './community-created--provision-member-and-default-role.ts'; +import RegisterStaffRoleDeletedReassignStaffUsersHandler from './staff-role-deleted--reassign-staff-users.ts'; export const RegisterIntegrationEventHandlers = (domainDataSource: DomainDataSource): void => { RegisterCommunityCreatedProvisionMemberAndDefaultRoleHandler(domainDataSource); + RegisterStaffRoleDeletedReassignStaffUsersHandler(domainDataSource); }; diff --git a/packages/ocom/event-handler/src/handlers/integration/staff-role-deleted--reassign-staff-users.ts b/packages/ocom/event-handler/src/handlers/integration/staff-role-deleted--reassign-staff-users.ts new file mode 100644 index 000000000..86daecb41 --- /dev/null +++ b/packages/ocom/event-handler/src/handlers/integration/staff-role-deleted--reassign-staff-users.ts @@ -0,0 +1,9 @@ +import { Domain, type DomainDataSource } from '@ocom/domain'; + +const { EventBusInstance, StaffRoleDeletedEvent } = Domain.Events; +export default (domainDataSource: DomainDataSource) => { + EventBusInstance.register(StaffRoleDeletedEvent, async (payload) => { + const { deletedRoleId, enterpriseAppRole } = payload; + return await Domain.Services.User.StaffRoleDeletedReassignmentService.reassignStaffUsersToDefaultRole(deletedRoleId, enterpriseAppRole, domainDataSource); + }); +}; diff --git a/packages/ocom/graphql/src/schema/types/features/staff-role.resolvers.feature b/packages/ocom/graphql/src/schema/types/features/staff-role.resolvers.feature new file mode 100644 index 000000000..0c7fec2f2 --- /dev/null +++ b/packages/ocom/graphql/src/schema/types/features/staff-role.resolvers.feature @@ -0,0 +1,19 @@ +Feature: StaffRole resolvers + + Scenario: Deleting a staff role successfully + Given a staff user with a verified JWT + When the staffRoleDelete mutation is executed for role "607f1f77bcf86cd799439099" + Then it should call User.StaffRole.delete with the role id + And it should return a success status + + Scenario: Unauthorized staff role deletion + Given a request without a verified JWT + When the staffRoleDelete mutation is executed without authentication + Then it should return an unauthorized failure status + And it should not call User.StaffRole.delete + + Scenario: Staff role deletion error handling + Given a staff user with a verified JWT + And the delete application service rejects with "You do not have permission to delete this role" + When the staffRoleDelete mutation is executed for role "607f1f77bcf86cd799439099" + Then it should return a failure status with the error message diff --git a/packages/ocom/graphql/src/schema/types/features/staff-user.resolvers.feature b/packages/ocom/graphql/src/schema/types/features/staff-user.resolvers.feature index d9f44a154..6c5816431 100644 --- a/packages/ocom/graphql/src/schema/types/features/staff-user.resolvers.feature +++ b/packages/ocom/graphql/src/schema/types/features/staff-user.resolvers.feature @@ -106,10 +106,10 @@ Feature: Staff User Resolvers When the staffRoleUpdate mutation is executed with id "role-001" and enterpriseAppRole "Staff.TechAdmin" Then it should return success with the updated staff role - Scenario: Updating a staff role with an unauthorized enterpriseAppRole + Scenario: Updating a staff role delegates enterpriseAppRole authorization to the application service Given a user with a verifiedJwt that includes the CaseManager role When the staffRoleUpdate mutation is executed with id "role-001" and enterpriseAppRole "Staff.TechAdmin" - Then it should return failure with a permission error message + Then it should return success with the updated staff role Scenario: Updating a staff role when unauthenticated Given a user without a verifiedJwt in their context diff --git a/packages/ocom/graphql/src/schema/types/staff-role.command-mapper.ts b/packages/ocom/graphql/src/schema/types/staff-role.command-mapper.ts index fd6232778..04d67fb33 100644 --- a/packages/ocom/graphql/src/schema/types/staff-role.command-mapper.ts +++ b/packages/ocom/graphql/src/schema/types/staff-role.command-mapper.ts @@ -7,8 +7,9 @@ import type { StaffRoleCommandUserPermissions, } from '../../../../application-services/src/contexts/user/staff-role/apply-permissions.js'; import type { StaffRoleCreateCommand } from '../../../../application-services/src/contexts/user/staff-role/create.js'; +import type { StaffRoleDeleteCommand } from '../../../../application-services/src/contexts/user/staff-role/delete.js'; import type { StaffRoleUpdateCommand } from '../../../../application-services/src/contexts/user/staff-role/update.js'; -import type { MutationStaffRoleCreateArgs, MutationStaffRoleUpdateArgs } from '../builder/generated.ts'; +import type { MutationStaffRoleCreateArgs, MutationStaffRoleDeleteArgs, MutationStaffRoleUpdateArgs } from '../builder/generated.ts'; const EnterpriseAppRoleNames = { CaseManager: 'Staff.CaseManager', @@ -70,3 +71,9 @@ export function buildStaffRoleUpdateCommand(input: NonNullable): StaffRoleDeleteCommand { + return { + roleId: String(input.id), + }; +} diff --git a/packages/ocom/graphql/src/schema/types/staff-role.graphql b/packages/ocom/graphql/src/schema/types/staff-role.graphql index 0f0b7fb3c..22d5000a6 100644 --- a/packages/ocom/graphql/src/schema/types/staff-role.graphql +++ b/packages/ocom/graphql/src/schema/types/staff-role.graphql @@ -127,6 +127,14 @@ type StaffRoleMutationResult implements MutationResult { staffRole: StaffRole } +input StaffRoleDeleteInput { + id: ObjectID! +} + +type StaffRoleDeleteMutationResult implements MutationResult { + status: MutationStatus! +} + extend type Query { staffRoles: [StaffRole!]! staffRoleById(id: ObjectID!): StaffRole @@ -135,4 +143,5 @@ extend type Query { extend type Mutation { staffRoleCreate(input: StaffRoleCreateInput!): StaffRoleMutationResult! staffRoleUpdate(input: StaffRoleUpdateInput!): StaffRoleMutationResult! + staffRoleDelete(input: StaffRoleDeleteInput!): StaffRoleDeleteMutationResult! } diff --git a/packages/ocom/graphql/src/schema/types/staff-role.resolvers.test.ts b/packages/ocom/graphql/src/schema/types/staff-role.resolvers.test.ts new file mode 100644 index 000000000..6ff814c2d --- /dev/null +++ b/packages/ocom/graphql/src/schema/types/staff-role.resolvers.test.ts @@ -0,0 +1,110 @@ +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { describeFeature, loadFeature } from '@amiceli/vitest-cucumber'; +import type { GraphQLResolveInfo } from 'graphql'; +import { expect, vi } from 'vitest'; +import type { MutationStaffRoleDeleteArgs, RequireFields } from '../builder/generated.ts'; +import type { GraphContext } from '../context.ts'; +import staffRoleResolvers from './staff-role.resolvers.ts'; + +const test = { for: describeFeature }; +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const feature = await loadFeature(path.resolve(__dirname, 'features/staff-role.resolvers.feature')); + +type StaffRoleDeleteResolver = (parent: unknown, args: RequireFields, context: GraphContext, info: GraphQLResolveInfo) => Promise<{ status: { success: boolean; errorMessage?: string } }>; + +function makeMockGraphContext(verified: boolean): GraphContext { + return { + applicationServices: { + User: { + StaffRole: { + delete: vi.fn(), + }, + }, + ...(verified + ? { + verifiedUser: { + verifiedJwt: { + sub: 'staff-user-sub', + roles: ['Staff.TechAdmin'], + }, + }, + } + : {}), + }, + } as unknown as GraphContext; +} + +test.for(feature, ({ Scenario, BeforeEachScenario }) => { + let context: GraphContext; + let result: { status: { success: boolean; errorMessage?: string } }; + + const executeDelete = async (roleId: string) => { + const resolver = staffRoleResolvers.Mutation?.staffRoleDelete as unknown as StaffRoleDeleteResolver; + result = await resolver(null, { input: { id: roleId } }, context, {} as GraphQLResolveInfo); + }; + + BeforeEachScenario(() => { + vi.clearAllMocks(); + context = makeMockGraphContext(true); + }); + + Scenario('Deleting a staff role successfully', ({ Given, When, Then, And }) => { + Given('a staff user with a verified JWT', () => { + context = makeMockGraphContext(true); + }); + + When('the staffRoleDelete mutation is executed for role "607f1f77bcf86cd799439099"', async () => { + vi.mocked(context.applicationServices.User.StaffRole.delete).mockResolvedValue(undefined); + await executeDelete('607f1f77bcf86cd799439099'); + }); + + Then('it should call User.StaffRole.delete with the role id', () => { + expect(context.applicationServices.User.StaffRole.delete).toHaveBeenCalledWith({ + roleId: '607f1f77bcf86cd799439099', + }); + }); + + And('it should return a success status', () => { + expect(result.status.success).toBe(true); + }); + }); + + Scenario('Unauthorized staff role deletion', ({ Given, When, Then, And }) => { + Given('a request without a verified JWT', () => { + context = makeMockGraphContext(false); + }); + + When('the staffRoleDelete mutation is executed without authentication', async () => { + await executeDelete('607f1f77bcf86cd799439099'); + }); + + Then('it should return an unauthorized failure status', () => { + expect(result.status.success).toBe(false); + expect(result.status.errorMessage).toBe('Unauthorized'); + }); + + And('it should not call User.StaffRole.delete', () => { + expect(context.applicationServices.User.StaffRole.delete).not.toHaveBeenCalled(); + }); + }); + + Scenario('Staff role deletion error handling', ({ Given, And, When, Then }) => { + Given('a staff user with a verified JWT', () => { + context = makeMockGraphContext(true); + }); + + And('the delete application service rejects with "You do not have permission to delete this role"', () => { + vi.mocked(context.applicationServices.User.StaffRole.delete).mockRejectedValue(new Error('You do not have permission to delete this role')); + }); + + When('the staffRoleDelete mutation is executed for role "607f1f77bcf86cd799439099"', async () => { + await executeDelete('607f1f77bcf86cd799439099'); + }); + + Then('it should return a failure status with the error message', () => { + expect(result.status.success).toBe(false); + expect(result.status.errorMessage).toBe('You do not have permission to delete this role'); + }); + }); +}); diff --git a/packages/ocom/graphql/src/schema/types/staff-role.resolvers.ts b/packages/ocom/graphql/src/schema/types/staff-role.resolvers.ts index 1b8bd6606..818e9c5d9 100644 --- a/packages/ocom/graphql/src/schema/types/staff-role.resolvers.ts +++ b/packages/ocom/graphql/src/schema/types/staff-role.resolvers.ts @@ -1,7 +1,7 @@ import type { GraphQLResolveInfo } from 'graphql'; -import type { MutationStaffRoleCreateArgs, MutationStaffRoleUpdateArgs, RequireFields, Resolvers } from '../builder/generated.ts'; +import type { MutationStaffRoleCreateArgs, MutationStaffRoleDeleteArgs, MutationStaffRoleUpdateArgs, RequireFields, Resolvers } from '../builder/generated.ts'; import type { GraphContext } from '../context.ts'; -import { buildStaffRoleCreateCommand, buildStaffRoleUpdateCommand } from './staff-role.command-mapper.ts'; +import { buildStaffRoleCreateCommand, buildStaffRoleDeleteCommand, buildStaffRoleUpdateCommand } from './staff-role.command-mapper.ts'; const staffRole: Resolvers = { Query: { @@ -56,6 +56,22 @@ const staffRole: Resolvers = { return { status: { success: false, errorMessage: message } }; } }, + + staffRoleDelete: async (_parent, args: RequireFields, context: GraphContext, _info: GraphQLResolveInfo) => { + const jwt = context.applicationServices.verifiedUser?.verifiedJwt; + if (!jwt) { + return { status: { success: false, errorMessage: 'Unauthorized' } }; + } + try { + const command = buildStaffRoleDeleteCommand(args.input); + await context.applicationServices.User.StaffRole.delete(command); + return { status: { success: true } }; + } catch (error) { + console.error('StaffRole > staffRoleDelete: ', error); + const { message } = error as Error; + return { status: { success: false, errorMessage: message } }; + } + }, }, }; diff --git a/packages/ocom/graphql/src/schema/types/staff-user.resolvers.test.ts b/packages/ocom/graphql/src/schema/types/staff-user.resolvers.test.ts index a87e0e6b6..3f0331906 100644 --- a/packages/ocom/graphql/src/schema/types/staff-user.resolvers.test.ts +++ b/packages/ocom/graphql/src/schema/types/staff-user.resolvers.test.ts @@ -451,10 +451,10 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { result = await callMutation('staffRoleCreate', context, { input: { roleName: 'New Role', enterpriseAppRole: 'Staff.TechAdmin' } }); }); - Then('it should return success with the updated staff role', () => { - const res = result as { status: { success: boolean }; staffRole: StaffRoleEntity }; - expect(res.status.success).toBe(true); - expect(res.staffRole).toBeDefined(); + Then('it should return failure with a permission error message', () => { + const { status } = result as { status: { success: boolean; errorMessage: string } }; + expect(status.success).toBe(false); + expect(status.errorMessage).toContain('do not have permission'); }); }); @@ -511,19 +511,21 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { }); }); - Scenario('Updating a staff role with an unauthorized enterpriseAppRole', ({ Given, When, Then }) => { + Scenario('Updating a staff role delegates enterpriseAppRole authorization to the application service', ({ Given, When, Then }) => { Given('a user with a verifiedJwt that includes the CaseManager role', () => { context = makeMockGraphContext({ jwt: { roles: ['Staff.CaseManager'] } }); }); When('the staffRoleUpdate mutation is executed with id "role-001" and enterpriseAppRole "Staff.TechAdmin"', async () => { + const mockRole = createMockStaffRole({ id: 'role-001', enterpriseAppRole: 'Staff.TechAdmin' }); + vi.mocked(context.applicationServices.User.StaffRole.update).mockResolvedValue(mockRole); result = await callMutation('staffRoleUpdate', context, { input: { id: 'role-001', roleName: 'Updated', enterpriseAppRole: 'Staff.TechAdmin' } }); }); - Then('it should return success with the updated staff user', () => { - const res = result as { status: { success: boolean }; staffUser: StaffUserEntity }; + Then('it should return success with the updated staff role', () => { + const res = result as { status: { success: boolean }; staffRole: StaffRoleEntity }; expect(res.status.success).toBe(true); - expect(res.staffUser).toBeDefined(); + expect(res.staffRole).toBeDefined(); }); }); @@ -597,6 +599,7 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { }); When('the staffUserAssignRole mutation is executed with staffUserId "user-001" and roleId "role-001"', async () => { + vi.mocked(context.applicationServices.User.StaffUser.assignRole).mockRejectedValue(new Error('You do not have permission to assign a role with enterprise app role type: Staff.TechAdmin')); result = await callMutation('staffUserAssignRole', context, { input: { staffUserId: 'user-001', roleId: 'role-001' } }); }); diff --git a/packages/ocom/persistence/src/datasources/domain/user/staff-user/features/staff-user.repository.feature b/packages/ocom/persistence/src/datasources/domain/user/staff-user/features/staff-user.repository.feature index b7cf1157c..85891c188 100644 --- a/packages/ocom/persistence/src/datasources/domain/user/staff-user/features/staff-user.repository.feature +++ b/packages/ocom/persistence/src/datasources/domain/user/staff-user/features/staff-user.repository.feature @@ -25,6 +25,16 @@ Feature: StaffUserRepository When I call getByExternalId with "87654321-4321-4321-4321-210987654321" Then it should throw an error indicating "StaffUser with externalId 87654321-4321-4321-4321-210987654321 not found" + Scenario: Getting all staff users assigned to a role + Given two staff users are assigned to the role with ID "607f1f77bcf86cd799439099" + When I call getAllAssignedToRole with "607f1f77bcf86cd799439099" + Then it should return the staff user aggregates assigned to that role + + Scenario: Getting all staff users assigned to a role with no assignees + Given no staff users are assigned to the role with ID "607f1f77bcf86cd799439100" + When I call getAllAssignedToRole with "607f1f77bcf86cd799439100" + Then it should return an empty list + Scenario: Creating a new staff user instance Given valid parameters for a new staff user When I call getNewInstance with externalId "12345678-1234-1234-8123-123456789012", firstName "John", lastName "Doe", email "john.doe@example.com" diff --git a/packages/ocom/persistence/src/datasources/domain/user/staff-user/staff-user.repository.test.ts b/packages/ocom/persistence/src/datasources/domain/user/staff-user/staff-user.repository.test.ts index f59ffa3a0..baa0710bc 100644 --- a/packages/ocom/persistence/src/datasources/domain/user/staff-user/staff-user.repository.test.ts +++ b/packages/ocom/persistence/src/datasources/domain/user/staff-user/staff-user.repository.test.ts @@ -1,14 +1,13 @@ -import type { EventBus } from '@cellix/domain-seedwork/event-bus'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { describeFeature, loadFeature } from '@amiceli/vitest-cucumber'; -import { expect, vi } from 'vitest'; +import type { EventBus } from '@cellix/domain-seedwork/event-bus'; +import type { StaffUser, StaffUserModelType } from '@ocom/data-sources-mongoose-models/user/staff-user'; import { Domain } from '@ocom/domain'; - -import { StaffUserRepository } from './staff-user.repository.ts'; -import { StaffUserConverter, type StaffUserDomainAdapter } from './staff-user.domain-adapter.ts'; import type { ClientSession } from 'mongoose'; -import type { StaffUser, StaffUserModelType } from '@ocom/data-sources-mongoose-models/user/staff-user'; +import { expect, vi } from 'vitest'; +import { StaffUserConverter, type StaffUserDomainAdapter } from './staff-user.domain-adapter.ts'; +import { StaffUserRepository } from './staff-user.repository.ts'; const test = { for: describeFeature }; const __dirname = path.dirname(fileURLToPath(import.meta.url)); @@ -82,6 +81,12 @@ test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { exec: vi.fn(async () => (query['externalId'] === '12345678-1234-1234-8123-123456789012' ? staffUserDoc : null)), })), })), + find: vi.fn((query: Record) => ({ + populate: vi.fn(() => ({ + // biome-ignore lint:useLiteralKeys + exec: vi.fn(async () => (query['role'] === '607f1f77bcf86cd799439099' ? [staffUserDoc, makeStaffUserDoc({ firstName: 'Jane' })] : [])), + })), + })), findByIdAndDelete: findByIdAndDeleteMock, }); @@ -157,6 +162,37 @@ test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { }); }); + Scenario('Getting all staff users assigned to a role', ({ Given, When, Then }) => { + let assigned: Domain.Contexts.User.StaffUser.StaffUser[]; + Given('two staff users are assigned to the role with ID "607f1f77bcf86cd799439099"', () => { + // Already mocked in BeforeEachScenario + }); + When('I call getAllAssignedToRole with "607f1f77bcf86cd799439099"', async () => { + assigned = await repo.getAllAssignedToRole('607f1f77bcf86cd799439099'); + }); + Then('it should return the staff user aggregates assigned to that role', () => { + expect(assigned).toHaveLength(2); + for (const staffUser of assigned) { + expect(staffUser).toBeInstanceOf(Domain.Contexts.User.StaffUser.StaffUser); + } + expect(assigned[0]?.firstName).toBe('John'); + expect(assigned[1]?.firstName).toBe('Jane'); + }); + }); + + Scenario('Getting all staff users assigned to a role with no assignees', ({ Given, When, Then }) => { + let assigned: Domain.Contexts.User.StaffUser.StaffUser[]; + Given('no staff users are assigned to the role with ID "607f1f77bcf86cd799439100"', () => { + // Already mocked to return an empty list + }); + When('I call getAllAssignedToRole with "607f1f77bcf86cd799439100"', async () => { + assigned = await repo.getAllAssignedToRole('607f1f77bcf86cd799439100'); + }); + Then('it should return an empty list', () => { + expect(assigned).toEqual([]); + }); + }); + Scenario('Creating a new staff user instance', ({ Given, When, Then, And }) => { Given('valid parameters for a new staff user', () => { // Already set up diff --git a/packages/ocom/persistence/src/datasources/domain/user/staff-user/staff-user.repository.ts b/packages/ocom/persistence/src/datasources/domain/user/staff-user/staff-user.repository.ts index 4660ba5a7..df54f84c9 100644 --- a/packages/ocom/persistence/src/datasources/domain/user/staff-user/staff-user.repository.ts +++ b/packages/ocom/persistence/src/datasources/domain/user/staff-user/staff-user.repository.ts @@ -1,8 +1,7 @@ import { MongooseSeedwork } from '@cellix/mongoose-seedwork'; - +import type { StaffUser } from '@ocom/data-sources-mongoose-models/user/staff-user'; import { Domain } from '@ocom/domain'; import type { StaffUserDomainAdapter } from './staff-user.domain-adapter.ts'; -import type { StaffUser } from '@ocom/data-sources-mongoose-models/user/staff-user'; type StaffUserDocument = StaffUser; type StaffUserAggregate = Domain.Contexts.User.StaffUser.StaffUser; @@ -29,6 +28,11 @@ export class StaffUserRepository extends MongooseSeedwork.MongoRepositoryBase { + const staffUsers = await this.model.find({ role: roleId }).populate('role').exec(); + return staffUsers.map((staffUser) => this.typeConverter.toDomain(staffUser, this.passport)); + } + getNewInstance(externalId: string, firstName: string, lastName: string, email: string): Promise { const adapter = this.typeConverter.toAdapter(new this.model()); adapter.tags = []; diff --git a/packages/ocom/ui-staff-route-user-management/.storybook/preview.tsx b/packages/ocom/ui-staff-route-user-management/.storybook/preview.tsx index 2f9935493..93750e37d 100644 --- a/packages/ocom/ui-staff-route-user-management/.storybook/preview.tsx +++ b/packages/ocom/ui-staff-route-user-management/.storybook/preview.tsx @@ -9,10 +9,7 @@ export const decorators: Decorator[] = [ const apolloMocks = context.parameters?.apolloMocks ?? []; return ( - + diff --git a/packages/ocom/ui-staff-route-user-management/src/components/staff-role-create.test.tsx b/packages/ocom/ui-staff-route-user-management/src/components/staff-role-create.test.tsx new file mode 100644 index 000000000..59189ae55 --- /dev/null +++ b/packages/ocom/ui-staff-route-user-management/src/components/staff-role-create.test.tsx @@ -0,0 +1,155 @@ +import { act } from 'react'; +import { createRoot } from 'react-dom/client'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { StaffRoleCreate } from './staff-role-create.tsx'; + +Object.defineProperty(window, 'matchMedia', { + writable: true, + value: vi.fn().mockImplementation((query: string) => ({ + matches: false, + media: query, + onchange: null, + addListener: vi.fn(), + removeListener: vi.fn(), + addEventListener: vi.fn(), + removeEventListener: vi.fn(), + dispatchEvent: vi.fn(), + })), +}); + +class ResizeObserverStub { + observe(): void { + // intentional no-op for jsdom + } + unobserve(): void { + // intentional no-op for jsdom + } + disconnect(): void { + // intentional no-op for jsdom + } +} +window.ResizeObserver = window.ResizeObserver ?? (ResizeObserverStub as unknown as typeof ResizeObserver); + +const findButtonByText = (rendered: HTMLElement, text: string): HTMLButtonElement | undefined => Array.from(rendered.querySelectorAll('button')).find((button) => (button.textContent ?? '').trim() === text); + +const clickButton = (button: HTMLButtonElement): void => { + act(() => { + button.dispatchEvent(new MouseEvent('click', { bubbles: true })); + }); +}; + +describe('StaffRoleCreate', () => { + let container!: HTMLDivElement; + let root!: ReturnType; + + const defaultProps = { + onSubmit: vi.fn(), + onCancel: vi.fn(), + availableEnterpriseAppRoles: ['Staff.CaseManager', 'Staff.TechAdmin'], + }; + + const renderComponent = (props: Partial[0]> = {}): HTMLDivElement => { + container = document.createElement('div'); + document.body.appendChild(container); + root = createRoot(container); + act(() => { + root.render( + , + ); + }); + return container; + }; + + beforeEach(() => { + vi.clearAllMocks(); + }); + + afterEach(() => { + act(() => { + root?.unmount(); + }); + container?.remove(); + }); + + describe('titles', () => { + it('renders the create title in create mode', () => { + const rendered = renderComponent(); + expect(rendered.textContent).toContain('Create Staff Role'); + }); + + it('renders the edit title in edit mode', () => { + const rendered = renderComponent({ mode: 'edit' }); + expect(rendered.textContent).toContain('Edit Staff Role'); + }); + }); + + describe('delete action visibility', () => { + it('renders the delete action for a deletable role in edit mode', () => { + const rendered = renderComponent({ mode: 'edit', showDelete: true, onDelete: vi.fn() }); + expect(findButtonByText(rendered, 'Delete Role')).toBeDefined(); + }); + + it('does not render the delete action when showDelete is false', () => { + const rendered = renderComponent({ mode: 'edit', showDelete: false, onDelete: vi.fn() }); + expect(findButtonByText(rendered, 'Delete Role')).toBeUndefined(); + }); + + it('does not render the delete action in create mode even when showDelete is set', () => { + const rendered = renderComponent({ mode: 'create', showDelete: true, onDelete: vi.fn() }); + expect(findButtonByText(rendered, 'Delete Role')).toBeUndefined(); + }); + + it('renders the delete action as a danger button', () => { + const rendered = renderComponent({ mode: 'edit', showDelete: true, onDelete: vi.fn() }); + const deleteButton = findButtonByText(rendered, 'Delete Role'); + expect(deleteButton?.className).toContain('ant-btn-dangerous'); + }); + }); + + describe('delete confirmation', () => { + it('shows a confirmation explaining reassignment to the matching default role', () => { + const rendered = renderComponent({ mode: 'edit', showDelete: true, onDelete: vi.fn() }); + const deleteButton = findButtonByText(rendered, 'Delete Role'); + expect(deleteButton).toBeDefined(); + clickButton(deleteButton as HTMLButtonElement); + + const confirmation = document.querySelector('.ant-popconfirm'); + expect(confirmation).not.toBeNull(); + expect(confirmation?.textContent).toMatch(/reassigned/i); + expect(confirmation?.textContent).toMatch(/default role/i); + }); + + it('calls onDelete when the confirmation is accepted', () => { + const onDelete = vi.fn(); + const rendered = renderComponent({ mode: 'edit', showDelete: true, onDelete }); + clickButton(findButtonByText(rendered, 'Delete Role') as HTMLButtonElement); + + const confirmButton = Array.from(document.querySelectorAll('.ant-popconfirm-buttons button')).find((button) => (button.textContent ?? '').trim() === 'Delete'); + expect(confirmButton).toBeDefined(); + clickButton(confirmButton as HTMLButtonElement); + expect(onDelete).toHaveBeenCalledTimes(1); + }); + + it('does not call onDelete when the confirmation is cancelled', () => { + const onDelete = vi.fn(); + const rendered = renderComponent({ mode: 'edit', showDelete: true, onDelete }); + clickButton(findButtonByText(rendered, 'Delete Role') as HTMLButtonElement); + + const cancelButton = Array.from(document.querySelectorAll('.ant-popconfirm-buttons button')).find((button) => (button.textContent ?? '').trim() === 'Cancel'); + expect(cancelButton).toBeDefined(); + clickButton(cancelButton as HTMLButtonElement); + expect(onDelete).not.toHaveBeenCalled(); + }); + }); + + describe('deletion in progress', () => { + it('shows the delete button in a loading state while deleting', () => { + const rendered = renderComponent({ mode: 'edit', showDelete: true, onDelete: vi.fn(), deleting: true }); + const deleteButton = findButtonByText(rendered, 'Delete Role'); + expect(deleteButton?.className).toContain('ant-btn-loading'); + }); + }); +}); diff --git a/packages/ocom/ui-staff-route-user-management/src/components/staff-role-create.tsx b/packages/ocom/ui-staff-route-user-management/src/components/staff-role-create.tsx index f4613977b..be25181af 100644 --- a/packages/ocom/ui-staff-route-user-management/src/components/staff-role-create.tsx +++ b/packages/ocom/ui-staff-route-user-management/src/components/staff-role-create.tsx @@ -1,4 +1,4 @@ -import { Button, Checkbox, Divider, Form, Input, Select, Space, Typography } from 'antd'; +import { Button, Checkbox, Divider, Form, Input, Popconfirm, Select, Space, Typography } from 'antd'; import type React from 'react'; const { Title } = Typography; @@ -38,6 +38,9 @@ interface StaffRoleCreateProps { showTechAdminPermissions?: boolean; initialValues?: Partial; mode?: 'create' | 'edit'; + showDelete?: boolean; + onDelete?: () => void; + deleting?: boolean; } type PermissionFieldKey = keyof Omit; @@ -143,7 +146,7 @@ const DEFAULT_VALUES: StaffRoleFormValues = { canSendQueueMessages: false, }; -export const StaffRoleCreate: React.FC = ({ onSubmit, onCancel, loading, availableEnterpriseAppRoles, showTechAdminPermissions, initialValues, mode = 'create' }) => { +export const StaffRoleCreate: React.FC = ({ onSubmit, onCancel, loading, availableEnterpriseAppRoles, showTechAdminPermissions, initialValues, mode = 'create', showDelete, onDelete, deleting }) => { const [form] = Form.useForm(); const defaultValues: StaffRoleFormValues = { @@ -172,7 +175,32 @@ export const StaffRoleCreate: React.FC = ({ onSubmit, onCa size="large" style={{ width: '100%', maxWidth: 720 }} > - {isEdit ? 'Edit Staff Role' : 'Create Staff Role'} +
+ + {isEdit ? 'Edit Staff Role' : 'Create Staff Role'} + + {isEdit && showDelete && onDelete && ( + trigger.parentElement ?? document.body} + > + + + )} +
= { + title: 'UserManagement/Containers/StaffRoleEditContainer', + component: StaffRoleEditContainer, + parameters: { layout: 'padded' }, + decorators: [ + (Story) => ( + + + + Staff Roles List} + /> + } + /> + + + + ), + ], +}; + +export default meta; +type Story = StoryObj; + +/** Deleting the role fails server-side: an error message is shown and the user stays on the details page. */ +export const DeleteFailure: Story = { + parameters: { + memoryRouter: { initialEntries: [`/roles/edit/${ROLE_ID}`] }, + apolloMocks: [ + staffRoleByIdMock, + staffRolesListMock, + { + request: { query: StaffRoleDeleteDocument, variables: { input: { id: ROLE_ID } } }, + result: { + data: { + staffRoleDelete: { + __typename: 'StaffRoleDeleteMutationResult' as const, + status: { __typename: 'MutationStatus' as const, success: false, errorMessage: 'Deletion rejected by the server' }, + }, + }, + }, + }, + ], + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + const deleteButton = await canvas.findByRole('button', { name: /delete role/i }); + await userEvent.click(deleteButton); + + await waitFor(() => { + expect(canvasElement.querySelector('.ant-popconfirm')).not.toBeNull(); + }); + const confirmButton = canvasElement.querySelector('.ant-popconfirm-buttons .ant-btn-primary'); + expect(confirmButton).not.toBeNull(); + await userEvent.click(confirmButton as HTMLButtonElement); + + await waitFor(() => { + expect(document.body.textContent).toMatch(/Failed to delete role/i); + }); + expect(await canvas.findByRole('button', { name: /delete role/i })).toBeVisible(); + }, +}; diff --git a/packages/ocom/ui-staff-route-user-management/src/components/staff-role-edit.container.tsx b/packages/ocom/ui-staff-route-user-management/src/components/staff-role-edit.container.tsx index 99d73c4aa..a7d7b69c7 100644 --- a/packages/ocom/ui-staff-route-user-management/src/components/staff-role-edit.container.tsx +++ b/packages/ocom/ui-staff-route-user-management/src/components/staff-role-edit.container.tsx @@ -4,7 +4,7 @@ import { App, Spin } from 'antd'; import type React from 'react'; import { useContext } from 'react'; import { Navigate, useNavigate, useParams } from 'react-router-dom'; -import { StaffRoleByIdDocument, StaffRolesListDocument, StaffRoleUpdateDocument } from '../generated.tsx'; +import { StaffRoleByIdDocument, StaffRoleDeleteDocument, StaffRolesListDocument, StaffRoleUpdateDocument } from '../generated.tsx'; import { StaffRoleCreate, type StaffRoleFormValues } from './staff-role-create.tsx'; const EnterpriseAppRoleNames = { @@ -37,6 +37,7 @@ export const StaffRoleEditContainer: React.FC = () => { const availableEnterpriseAppRoles = getAllowedEnterpriseAppRoles(auth?.enterpriseAppRole); const showTechAdminPermissions = auth?.permissions?.canManageTechAdmin === true; const canEditRole = auth?.permissions?.canEditRole === true || auth?.permissions?.canManageStaffRolesAndPermissions === true || auth?.permissions?.canManageTechAdmin === true; + const canRemoveRole = auth?.permissions?.canRemoveRole === true; const { data, loading: queryLoading } = useQuery(StaffRoleByIdDocument, { variables: { id: id ?? '' }, @@ -47,6 +48,10 @@ export const StaffRoleEditContainer: React.FC = () => { refetchQueries: [{ query: StaffRolesListDocument }], }); + const [staffRoleDelete, { loading: deleteLoading }] = useMutation(StaffRoleDeleteDocument, { + refetchQueries: [{ query: StaffRolesListDocument }], + }); + if (!canEditRole) { return ( { navigate('..'); }; + const handleDelete = async () => { + if (!id) return; + try { + const result = await staffRoleDelete({ + variables: { input: { id } }, + }); + if (result.data?.staffRoleDelete.status.success) { + message.success('Role deleted successfully'); + navigate('..'); + } else { + message.error(`Failed to delete role: ${result.data?.staffRoleDelete.status.errorMessage ?? 'Unknown error'}`); + } + } catch (_err) { + message.error('Failed to delete role'); + } + }; + if (queryLoading) { return (
@@ -168,6 +190,9 @@ export const StaffRoleEditContainer: React.FC = () => { availableEnterpriseAppRoles={availableEnterpriseAppRoles} showTechAdminPermissions={showTechAdminPermissions} initialValues={initialValues} + showDelete={canRemoveRole && role?.isDefault === false} + onDelete={handleDelete} + deleting={deleteLoading} /> ); }; diff --git a/packages/ocom/ui-staff-route-user-management/src/components/staff-role-edit.stories.tsx b/packages/ocom/ui-staff-route-user-management/src/components/staff-role-edit.stories.tsx index a392b5c63..49b9403b0 100644 --- a/packages/ocom/ui-staff-route-user-management/src/components/staff-role-edit.stories.tsx +++ b/packages/ocom/ui-staff-route-user-management/src/components/staff-role-edit.stories.tsx @@ -1,4 +1,5 @@ import type { Meta, StoryObj } from '@storybook/react'; +import { expect, userEvent, waitFor, within } from 'storybook/test'; import { StaffRoleCreate } from './staff-role-create.tsx'; const ALL_ENTERPRISE_APP_ROLES = ['Staff.TechAdmin', 'Staff.ServiceLineOwner', 'Staff.CaseManager', 'Staff.Finance']; @@ -97,3 +98,108 @@ export const WithSaving: Story = { initialValues: existingRoleValues, }, }; + +/** Non-default role viewed by a staff user with the remove-role permission: the delete action is available. */ +export const DeletableRole: Story = { + args: { + mode: 'edit', + onSubmit: (values) => console.log('Submit:', values), + onCancel: () => console.log('Cancel clicked'), + availableEnterpriseAppRoles: ALL_ENTERPRISE_APP_ROLES, + showTechAdminPermissions: true, + initialValues: existingRoleValues, + showDelete: true, + onDelete: () => console.log('Delete confirmed'), + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + const deleteButton = await canvas.findByRole('button', { name: /delete role/i }); + expect(deleteButton).toBeVisible(); + }, +}; + +/** Default roles are never deletable, so the container hides the delete action (`showDelete: false`). */ +export const DefaultRoleDeletionUnavailable: Story = { + args: { + mode: 'edit', + onSubmit: (values) => console.log('Submit:', values), + onCancel: () => console.log('Cancel clicked'), + availableEnterpriseAppRoles: ALL_ENTERPRISE_APP_ROLES, + showTechAdminPermissions: true, + initialValues: { ...existingRoleValues, roleName: 'Default Finance' }, + showDelete: false, + onDelete: () => console.log('Delete confirmed'), + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + await waitFor(() => { + expect(canvas.queryByRole('button', { name: /delete role/i })).toBeNull(); + }); + }, +}; + +/** Viewer lacks `staffRolePermissions.canRemoveRole`, so the container hides the delete action (`showDelete: false`). */ +export const WithoutRemoveRolePermission: Story = { + args: { + mode: 'edit', + onSubmit: (values) => console.log('Submit:', values), + onCancel: () => console.log('Cancel clicked'), + availableEnterpriseAppRoles: ALL_ENTERPRISE_APP_ROLES, + showTechAdminPermissions: true, + initialValues: existingRoleValues, + showDelete: false, + onDelete: () => console.log('Delete confirmed'), + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + await waitFor(() => { + expect(canvas.queryByRole('button', { name: /delete role/i })).toBeNull(); + }); + }, +}; + +/** Clicking the delete action opens a confirmation explaining staff-user reassignment to the matching default role. */ +export const DeleteConfirmation: Story = { + args: { + mode: 'edit', + onSubmit: (values) => console.log('Submit:', values), + onCancel: () => console.log('Cancel clicked'), + availableEnterpriseAppRoles: ALL_ENTERPRISE_APP_ROLES, + showTechAdminPermissions: true, + initialValues: existingRoleValues, + showDelete: true, + onDelete: () => console.log('Delete confirmed'), + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + const deleteButton = await canvas.findByRole('button', { name: /delete role/i }); + await userEvent.click(deleteButton); + + await waitFor(() => { + const confirmation = canvasElement.querySelector('.ant-popconfirm'); + expect(confirmation).not.toBeNull(); + expect(confirmation?.textContent).toMatch(/reassigned/i); + expect(confirmation?.textContent).toMatch(/default role/i); + }); + }, +}; + +/** Deletion mutation in flight: the delete action shows a loading state. */ +export const DeletionInProgress: Story = { + args: { + mode: 'edit', + onSubmit: (values) => console.log('Submit:', values), + onCancel: () => console.log('Cancel clicked'), + availableEnterpriseAppRoles: ALL_ENTERPRISE_APP_ROLES, + showTechAdminPermissions: true, + initialValues: existingRoleValues, + showDelete: true, + onDelete: () => console.log('Delete confirmed'), + deleting: true, + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + const deleteButton = await canvas.findByRole('button', { name: /delete role/i }); + expect(deleteButton.className).toContain('ant-btn-loading'); + }, +}; diff --git a/packages/ocom/ui-staff-route-user-management/src/components/staff-user-detail.test.tsx b/packages/ocom/ui-staff-route-user-management/src/components/staff-user-detail.test.tsx index cc54efc46..f0c1bcffc 100644 --- a/packages/ocom/ui-staff-route-user-management/src/components/staff-user-detail.test.tsx +++ b/packages/ocom/ui-staff-route-user-management/src/components/staff-user-detail.test.tsx @@ -61,7 +61,7 @@ describe('StaffUserDetail', () => { onSave: vi.fn(), }; - const renderComponent = (props = defaultProps): HTMLDivElement => { + const renderComponent = (props: Parameters[0] = defaultProps): HTMLDivElement => { container = document.createElement('div'); document.body.appendChild(container); root = createRoot(container); @@ -173,10 +173,8 @@ describe('StaffUserDetail', () => { availableRoles: [{ id: 'r1', roleName: 'Tech Admin' }], }); // The Select value is the ID; the rendered option label must show the role name. - // antd renders the selected label in the combobox title attribute. - const _combobox = rendered.querySelector('[role="combobox"]'); // The title on the selection item or the input's value should reflect the label, not the raw ID - const selectionItem = rendered.querySelector('.ant-select-selection-item'); + const selectionItem = rendered.querySelector('.ant-select-selection-item, .ant-select-content'); const displayText = selectionItem?.getAttribute('title') ?? selectionItem?.textContent ?? ''; expect(displayText).toBe('Tech Admin'); }); diff --git a/packages/ocom/ui-staff-route-user-management/tsconfig.vitest.json b/packages/ocom/ui-staff-route-user-management/tsconfig.vitest.json new file mode 100644 index 000000000..4f806efbc --- /dev/null +++ b/packages/ocom/ui-staff-route-user-management/tsconfig.vitest.json @@ -0,0 +1,3 @@ +{ + "extends": ["./tsconfig.json", "@cellix/config-typescript/vitest"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9c1b08443..2c79b53cf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -70,8 +70,8 @@ catalogs: specifier: 7.0.0-dev.20260428.1 version: 7.0.0-dev.20260428.1 '@vitest/coverage-istanbul': - specifier: 4.1.8 - version: 4.1.8 + specifier: 4.1.10 + version: 4.1.10 antd: specifier: 6.3.5 version: 6.3.5 @@ -118,14 +118,14 @@ catalogs: specifier: ^0.28.0 version: 0.28.0 vitest: - specifier: 4.1.8 - version: 4.1.8 + specifier: 4.1.10 + version: 4.1.10 overrides: - '@vitest/browser': 4.1.8 - '@vitest/browser-playwright': 4.1.8 + '@vitest/browser': 4.1.10 + '@vitest/browser-playwright': 4.1.10 happy-dom: 20.10.1 - axios: 1.16.0 + axios: 1.18.0 body-parser: 2.3.0 esbuild: 0.28.1 follow-redirects: ^1.16.0 @@ -140,7 +140,9 @@ overrides: serve-handler>minimatch: 3.1.5 serialize-javascript@6.0.2: 7.0.5 serialize-javascript@7.0.4: 7.0.5 - svgo: ^3.3.3 + svgo: ^3.3.4 + '@opentelemetry/propagator-jaeger': ^2.9.0 + websocket-driver: ^0.7.5 yaml@2.8.2: 2.8.3 yauzl@3.2.0: 3.2.1 qs: 6.15.2 @@ -163,7 +165,7 @@ overrides: postcss: 8.5.10 protobufjs: 7.6.5 ip-address: ^10.1.1 - fast-uri: ^4.0.1 + fast-uri: ^4.1.1 '@babel/plugin-transform-modules-systemjs': 7.29.4 '@babel/core': ^7.29.6 js-yaml: 4.3.0 @@ -171,7 +173,7 @@ overrides: shell-quote@<1.8.4: 1.8.4 '@opentelemetry/exporter-prometheus@0.57.2': 0.217.0 '@opentelemetry/core@2.7.1': 2.8.0 - ws: 8.21.0 + ws: 8.21.1 shell-quote: 1.9.0 '@grpc/grpc-js': '>=1.14.4' form-data: ^4.0.6 @@ -200,7 +202,7 @@ importers: devDependencies: '@amiceli/vitest-cucumber': specifier: ^6.3.0 - version: 6.3.0(vitest@4.1.8) + version: 6.3.0(vitest@4.1.10) '@ant-design/cli': specifier: ^6.3.5 version: 6.3.5(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) @@ -236,7 +238,7 @@ importers: version: 1.59.0 '@sonar/scan': specifier: ^4.3.0 - version: 4.3.2 + version: 4.3.2(supports-color@8.1.1) '@types/node': specifier: 'catalog:' version: 22.19.15 @@ -245,7 +247,7 @@ importers: version: 7.0.0-dev.20260428.1 '@vitest/coverage-istanbul': specifier: 'catalog:' - version: 4.1.8(supports-color@8.1.1)(vitest@4.1.8) + version: 4.1.10(supports-color@8.1.1)(vitest@4.1.10) chrome-devtools-mcp: specifier: ^1.3.0 version: 1.3.0 @@ -278,7 +280,7 @@ importers: version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) apps/api: dependencies: @@ -351,7 +353,7 @@ importers: version: link:../../packages/ocom/local-dev-config '@vitest/coverage-istanbul': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.8) + version: 4.1.10(vitest@4.1.10) archunit: specifier: 'catalog:' version: 2.1.63 @@ -369,19 +371,19 @@ importers: version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) apps/docs: dependencies: '@docusaurus/core': specifier: ^3.10.1 - version: 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) + version: 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) '@docusaurus/plugin-content-docs': specifier: ^3.10.1 - version: 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) + version: 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) '@docusaurus/preset-classic': specifier: ^3.10.1 - version: 3.10.1(@algolia/client-search@5.45.0)(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(@types/react@19.2.7)(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(search-insights@2.17.3)(typescript@6.0.3) + version: 3.10.1(@algolia/client-search@5.45.0)(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(@types/react@19.2.7)(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(search-insights@2.17.3)(typescript@6.0.3) '@mdx-js/react': specifier: ^3.0.0 version: 3.1.1(@types/react@19.2.7)(react@19.2.0) @@ -409,13 +411,13 @@ importers: version: link:../../packages/cellix/local-dev '@docusaurus/module-type-aliases': specifier: ^3.10.1 - version: 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 3.10.1(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@docusaurus/tsconfig': specifier: ^3.10.1 version: 3.10.1 '@docusaurus/types': specifier: ^3.10.1 - version: 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@testing-library/jest-dom': specifier: ^6.6.3 version: 6.9.1 @@ -430,10 +432,10 @@ importers: version: 19.2.3(@types/react@19.2.7) '@vitejs/plugin-react': specifier: ^6.0.1 - version: 6.0.1(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 6.0.1(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) '@vitest/coverage-istanbul': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.8) + version: 4.1.10(vitest@4.1.10) jsdom: specifier: ^26.1.0 version: 26.1.0 @@ -442,7 +444,7 @@ importers: version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) apps/server-mongodb-memory-mock: dependencies: @@ -498,7 +500,7 @@ importers: version: link:../../packages/cellix/local-dev '@vitest/coverage-istanbul': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.8) + version: 4.1.10(vitest@4.1.10) rimraf: specifier: 'catalog:' version: 6.0.1 @@ -507,13 +509,13 @@ importers: version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) apps/ui-community: dependencies: '@apollo/client': specifier: ^3.13.9 - version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@cellix/ui-core': specifier: workspace:* version: link:../../packages/cellix/ui-core @@ -543,7 +545,7 @@ importers: version: 6.3.5(luxon@3.7.2)(moment@2.30.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) apollo-link-rest: specifier: ^0.9.0 - version: 0.9.0(@apollo/client@3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(graphql@16.12.0)(qs@6.15.2) + version: 0.9.0(@apollo/client@3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(graphql@16.12.0)(qs@6.15.2) less: specifier: ^4.4.0 version: 4.4.2 @@ -571,25 +573,25 @@ importers: version: link:../../packages/cellix/local-dev '@chromatic-com/storybook': specifier: ^5.2.1 - version: 5.2.1(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)) + version: 5.2.1(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0)) '@storybook/addon-a11y': specifier: 'catalog:' - version: 10.4.2(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)) + version: 10.4.2(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0)) '@storybook/addon-docs': specifier: 'catalog:' - version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) + version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)) '@storybook/addon-onboarding': specifier: 'catalog:' - version: 10.4.2(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)) + version: 10.4.2(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0)) '@storybook/addon-vitest': specifier: 'catalog:' - version: 10.4.2(@vitest/browser-playwright@4.1.8)(@vitest/browser@4.1.8(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.8))(@vitest/runner@4.1.8)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(vitest@4.1.8) + version: 10.4.2(@vitest/browser-playwright@4.1.10)(@vitest/browser@4.1.10(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.10))(@vitest/runner@4.1.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vitest@4.1.10) '@storybook/react': specifier: 10.4.2 - version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(typescript@6.0.3) + version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(typescript@6.0.3) '@storybook/react-vite': specifier: 'catalog:' - version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(typescript@6.0.3)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) + version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(typescript@6.0.3)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)) '@types/react': specifier: ^19.1.8 version: 19.2.7 @@ -598,10 +600,10 @@ importers: version: 19.2.3(@types/react@19.2.7) '@vitejs/plugin-react': specifier: ^6.0.1 - version: 6.0.1(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 6.0.1(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) '@vitest/coverage-istanbul': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.8) + version: 4.1.10(vitest@4.1.10) esbuild: specifier: 0.28.1 version: 0.28.1 @@ -613,10 +615,10 @@ importers: version: 6.0.5(rolldown@1.0.3) storybook: specifier: 'catalog:' - version: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0) storybook-addon-apollo-client: specifier: ^9.0.0 - version: 9.0.0(@apollo/client@3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(graphql@16.12.0)(react@19.2.0) + version: 9.0.0(@apollo/client@3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(graphql@16.12.0)(react@19.2.0) tailwindcss: specifier: ^3.4.17 version: 3.4.18(tsx@4.21.0)(yaml@2.8.3) @@ -625,19 +627,19 @@ importers: version: 6.0.3 vite: specifier: 8.0.16 - version: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + version: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) vite-plugin-node-polyfills: specifier: 'catalog:' - version: 0.28.0(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 0.28.0(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) apps/ui-staff: dependencies: '@apollo/client': specifier: ^3.13.9 - version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@cellix/ui-core': specifier: workspace:* version: link:../../packages/cellix/ui-core @@ -676,7 +678,7 @@ importers: version: 6.3.5(luxon@3.7.2)(moment@2.30.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) apollo-link-rest: specifier: ^0.9.0 - version: 0.9.0(@apollo/client@3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(graphql@16.12.0)(qs@6.15.2) + version: 0.9.0(@apollo/client@3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(graphql@16.12.0)(qs@6.15.2) less: specifier: ^4.4.0 version: 4.4.2 @@ -710,10 +712,10 @@ importers: version: 19.2.3(@types/react@19.2.7) '@vitejs/plugin-react': specifier: ^6.0.1 - version: 6.0.1(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 6.0.1(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) '@vitest/coverage-istanbul': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.8) + version: 4.1.10(vitest@4.1.10) esbuild: specifier: 0.28.1 version: 0.28.1 @@ -731,13 +733,13 @@ importers: version: 6.0.3 vite: specifier: 8.0.16 - version: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + version: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) vite-plugin-node-polyfills: specifier: 'catalog:' - version: 0.28.0(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 0.28.0(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/cellix/api-services-spec: devDependencies: @@ -773,7 +775,7 @@ importers: version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/cellix/config-rolldown: devDependencies: @@ -785,19 +787,19 @@ importers: version: link:../config-vitest '@vitest/coverage-istanbul': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.8) + version: 4.1.10(vitest@4.1.10) rimraf: specifier: 'catalog:' version: 6.0.1 rolldown: specifier: 1.0.0-beta.55 - version: 1.0.0-beta.55(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + version: 1.0.0-beta.55(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) typescript: specifier: 'catalog:' version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/cellix/config-typescript: {} @@ -808,16 +810,16 @@ importers: version: link:../config-typescript '@storybook/addon-vitest': specifier: 'catalog:' - version: 10.4.2(@vitest/browser-playwright@4.1.8)(@vitest/browser@4.1.8(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.8))(@vitest/runner@4.1.8)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(vitest@4.1.8) + version: 10.4.2(@vitest/browser-playwright@4.1.10)(@vitest/browser@4.1.10(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.10))(@vitest/runner@4.1.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vitest@4.1.10) '@vitest/browser-playwright': - specifier: 4.1.8 - version: 4.1.8(playwright@1.59.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.8) + specifier: 4.1.10 + version: 4.1.10(playwright@1.59.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.10) typescript: specifier: 'catalog:' version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/cellix/domain-seedwork: devDependencies: @@ -829,7 +831,7 @@ importers: version: link:../config-vitest '@vitest/coverage-istanbul': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.8) + version: 4.1.10(vitest@4.1.10) rimraf: specifier: 'catalog:' version: 6.0.1 @@ -838,7 +840,7 @@ importers: version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/cellix/event-bus-seedwork-node: dependencies: @@ -857,7 +859,7 @@ importers: version: link:../config-vitest '@vitest/coverage-istanbul': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.8) + version: 4.1.10(vitest@4.1.10) rimraf: specifier: 'catalog:' version: 6.0.1 @@ -888,7 +890,7 @@ importers: devDependencies: '@amiceli/vitest-cucumber': specifier: ^6.3.0 - version: 6.3.0(vitest@4.1.8) + version: 6.3.0(vitest@4.1.10) '@cellix/config-typescript': specifier: workspace:* version: link:../config-typescript @@ -897,7 +899,7 @@ importers: version: link:../config-vitest '@vitest/coverage-istanbul': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.8) + version: 4.1.10(vitest@4.1.10) rimraf: specifier: 'catalog:' version: 6.0.1 @@ -906,7 +908,7 @@ importers: version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/cellix/graphql-core: dependencies: @@ -925,7 +927,7 @@ importers: version: link:../config-vitest '@vitest/coverage-istanbul': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.8) + version: 4.1.10(vitest@4.1.10) rimraf: specifier: 'catalog:' version: 6.0.1 @@ -934,7 +936,7 @@ importers: version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/cellix/local-dev: devDependencies: @@ -949,7 +951,7 @@ importers: version: 22.19.15 '@vitest/coverage-istanbul': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.8) + version: 4.1.10(vitest@4.1.10) rimraf: specifier: 'catalog:' version: 6.0.1 @@ -958,7 +960,7 @@ importers: version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/cellix/mongoose-seedwork: dependencies: @@ -977,7 +979,7 @@ importers: version: link:../config-vitest '@vitest/coverage-istanbul': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.8) + version: 4.1.10(vitest@4.1.10) mongodb: specifier: 'catalog:' version: 6.18.0 @@ -995,7 +997,7 @@ importers: version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/cellix/serenity-framework: dependencies: @@ -1050,7 +1052,7 @@ importers: version: 19.2.7 '@vitest/coverage-istanbul': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.8) + version: 4.1.10(vitest@4.1.10) playwright: specifier: 1.59.0 version: 1.59.0 @@ -1065,7 +1067,7 @@ importers: version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/cellix/server-mongodb-memory-mock-seedwork: dependencies: @@ -1115,7 +1117,7 @@ importers: version: 5.0.5 '@vitest/coverage-istanbul': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.8) + version: 4.1.10(vitest@4.1.10) rimraf: specifier: 'catalog:' version: 6.0.1 @@ -1124,7 +1126,7 @@ importers: version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/cellix/service-blob-storage: dependencies: @@ -1146,7 +1148,7 @@ importers: version: link:../config-vitest '@vitest/coverage-istanbul': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.8) + version: 4.1.10(vitest@4.1.10) rimraf: specifier: 'catalog:' version: 6.0.1 @@ -1155,7 +1157,7 @@ importers: version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/cellix/service-queue-storage: dependencies: @@ -1180,7 +1182,7 @@ importers: devDependencies: '@amiceli/vitest-cucumber': specifier: ^6.3.0 - version: 6.3.0(vitest@4.1.8) + version: 6.3.0(vitest@4.1.10) '@cellix/config-typescript': specifier: workspace:* version: link:../config-typescript @@ -1189,7 +1191,7 @@ importers: version: link:../config-vitest '@vitest/coverage-istanbul': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.8) + version: 4.1.10(vitest@4.1.10) execa: specifier: ^9.6.0 version: 9.6.1 @@ -1201,7 +1203,7 @@ importers: version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/cellix/ui-core: dependencies: @@ -1223,25 +1225,25 @@ importers: version: link:../config-vitest '@chromatic-com/storybook': specifier: ^5.2.1 - version: 5.2.1(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)) + version: 5.2.1(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0)) '@storybook/addon-a11y': specifier: 'catalog:' - version: 10.4.2(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)) + version: 10.4.2(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0)) '@storybook/addon-docs': specifier: 'catalog:' - version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) + version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) '@storybook/addon-onboarding': specifier: 'catalog:' - version: 10.4.2(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)) + version: 10.4.2(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0)) '@storybook/addon-vitest': specifier: 'catalog:' - version: 10.4.2(@vitest/browser-playwright@4.1.8)(@vitest/browser@4.1.8(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.8))(@vitest/runner@4.1.8)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(vitest@4.1.8) + version: 10.4.2(@vitest/browser-playwright@4.1.10)(@vitest/browser@4.1.10(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.10))(@vitest/runner@4.1.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vitest@4.1.10) '@storybook/react': specifier: 10.4.2 - version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(typescript@6.0.3) + version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(typescript@6.0.3) '@storybook/react-vite': specifier: 'catalog:' - version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(typescript@6.0.3)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) + version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(typescript@6.0.3)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) '@testing-library/react': specifier: ^16.2.0 version: 16.3.0(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -1252,14 +1254,14 @@ importers: specifier: ^19.1.6 version: 19.2.3(@types/react@19.2.7) '@vitest/browser': - specifier: 4.1.8 - version: 4.1.8(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.8) + specifier: 4.1.10 + version: 4.1.10(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.10) '@vitest/browser-playwright': - specifier: 4.1.8 - version: 4.1.8(playwright@1.59.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.8) + specifier: 4.1.10 + version: 4.1.10(playwright@1.59.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.10) '@vitest/coverage-istanbul': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.8) + version: 4.1.10(vitest@4.1.10) jsdom: specifier: 'catalog:' version: 26.1.0 @@ -1274,13 +1276,13 @@ importers: version: 6.0.1 storybook: specifier: 'catalog:' - version: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0) typescript: specifier: 'catalog:' version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/ocom-verification/acceptance-api: dependencies: @@ -1336,6 +1338,9 @@ importers: '@ocom/data-sources-mongoose-models': specifier: workspace:* version: link:../../ocom/data-sources-mongoose-models + '@ocom/event-handler': + specifier: workspace:* + version: link:../../ocom/event-handler '@ocom/graphql': specifier: workspace:* version: link:../../ocom/graphql @@ -1380,7 +1385,7 @@ importers: dependencies: '@apollo/client': specifier: ^3.13.9 - version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@cellix/serenity-framework': specifier: workspace:* version: link:../../cellix/serenity-framework @@ -1471,7 +1476,7 @@ importers: version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/ocom-verification/e2e-tests: dependencies: @@ -1585,7 +1590,7 @@ importers: version: link:../../ocom-verification/archunit-tests '@vitest/coverage-istanbul': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.8) + version: 4.1.10(vitest@4.1.10) rimraf: specifier: 'catalog:' version: 6.0.1 @@ -1594,7 +1599,7 @@ importers: version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/ocom/context-spec: dependencies: @@ -1653,7 +1658,7 @@ importers: version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/ocom/domain: dependencies: @@ -1705,7 +1710,7 @@ importers: version: 3.43.0 '@vitest/coverage-istanbul': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.8) + version: 4.1.10(vitest@4.1.10) rimraf: specifier: 'catalog:' version: 6.0.1 @@ -1714,7 +1719,7 @@ importers: version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/ocom/event-handler: dependencies: @@ -1767,7 +1772,7 @@ importers: version: link:../../ocom-verification/archunit-tests '@vitest/coverage-istanbul': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.8) + version: 4.1.10(vitest@4.1.10) rimraf: specifier: 'catalog:' version: 6.0.1 @@ -1776,7 +1781,7 @@ importers: version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/ocom/graphql-handler: dependencies: @@ -1810,7 +1815,7 @@ importers: version: link:../../cellix/config-vitest '@vitest/coverage-istanbul': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.8) + version: 4.1.10(vitest@4.1.10) rimraf: specifier: 'catalog:' version: 6.0.1 @@ -1819,7 +1824,7 @@ importers: version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/ocom/local-dev-config: dependencies: @@ -1838,7 +1843,7 @@ importers: version: 22.19.15 '@vitest/coverage-istanbul': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.8) + version: 4.1.10(vitest@4.1.10) rimraf: specifier: 'catalog:' version: 6.0.1 @@ -1847,7 +1852,7 @@ importers: version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/ocom/persistence: dependencies: @@ -1887,7 +1892,7 @@ importers: version: link:../../ocom-verification/archunit-tests '@vitest/coverage-istanbul': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.8) + version: 4.1.10(vitest@4.1.10) rimraf: specifier: 'catalog:' version: 6.0.1 @@ -1896,7 +1901,7 @@ importers: version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/ocom/rest: dependencies: @@ -1949,7 +1954,7 @@ importers: version: 1.1.6 '@vitest/coverage-istanbul': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.8) + version: 4.1.10(vitest@4.1.10) rimraf: specifier: 'catalog:' version: 6.0.1 @@ -1958,7 +1963,7 @@ importers: version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/ocom/service-blob-storage: dependencies: @@ -1974,7 +1979,7 @@ importers: version: link:../../cellix/config-vitest '@vitest/coverage-istanbul': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.8) + version: 4.1.10(vitest@4.1.10) rimraf: specifier: 'catalog:' version: 6.0.1 @@ -1983,7 +1988,7 @@ importers: version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/ocom/service-mongoose: dependencies: @@ -2005,7 +2010,7 @@ importers: version: link:../../cellix/config-vitest '@vitest/coverage-istanbul': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.8) + version: 4.1.10(vitest@4.1.10) rimraf: specifier: 'catalog:' version: 6.0.1 @@ -2063,7 +2068,7 @@ importers: version: link:../../cellix/config-vitest '@vitest/coverage-istanbul': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.8) + version: 4.1.10(vitest@4.1.10) rimraf: specifier: 'catalog:' version: 6.0.1 @@ -2072,7 +2077,7 @@ importers: version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/ocom/service-queue-storage: dependencies: @@ -2088,7 +2093,7 @@ importers: version: link:../../cellix/config-vitest '@vitest/coverage-istanbul': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.8) + version: 4.1.10(vitest@4.1.10) rimraf: specifier: 'catalog:' version: 6.0.1 @@ -2097,7 +2102,7 @@ importers: version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/ocom/service-token-validation: dependencies: @@ -2116,7 +2121,7 @@ importers: version: link:../../cellix/config-vitest '@vitest/coverage-istanbul': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.8) + version: 4.1.10(vitest@4.1.10) rimraf: specifier: 'catalog:' version: 6.0.1 @@ -2125,7 +2130,7 @@ importers: version: 6.0.3 vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/ocom/ui-community-route-accounts: dependencies: @@ -2137,7 +2142,7 @@ importers: version: 7.22.7(antd@6.3.5(luxon@3.7.2)(moment@2.30.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@apollo/client': specifier: ^3.13.9 - version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@cellix/ui-core': specifier: workspace:* version: link:../../cellix/ui-core @@ -2180,25 +2185,25 @@ importers: version: link:../../cellix/config-vitest '@chromatic-com/storybook': specifier: ^5.2.1 - version: 5.2.1(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)) + version: 5.2.1(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0)) '@ocom-verification/archunit-tests': specifier: workspace:* version: link:../../ocom-verification/archunit-tests '@storybook/addon-a11y': specifier: 'catalog:' - version: 10.4.2(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)) + version: 10.4.2(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0)) '@storybook/addon-docs': specifier: 'catalog:' - version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) + version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) '@storybook/addon-vitest': specifier: 'catalog:' - version: 10.4.2(@vitest/browser-playwright@4.1.8)(@vitest/browser@4.1.8(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.8))(@vitest/runner@4.1.8)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(vitest@4.1.8) + version: 10.4.2(@vitest/browser-playwright@4.1.10)(@vitest/browser@4.1.10(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.10))(@vitest/runner@4.1.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vitest@4.1.10) '@storybook/react': specifier: 10.4.2 - version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(typescript@6.0.3) + version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(typescript@6.0.3) '@storybook/react-vite': specifier: 'catalog:' - version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(typescript@6.0.3)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) + version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(typescript@6.0.3)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) '@types/react': specifier: ^19.1.11 version: 19.2.7 @@ -2210,16 +2215,16 @@ importers: version: 26.1.0 storybook: specifier: 'catalog:' - version: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0) typescript: specifier: 'catalog:' version: 6.0.3 vite: specifier: 8.0.16 - version: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + version: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/ocom/ui-community-route-admin: dependencies: @@ -2231,7 +2236,7 @@ importers: version: 7.22.7(antd@6.3.5(luxon@3.7.2)(moment@2.30.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@apollo/client': specifier: ^3.13.9 - version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@cellix/ui-core': specifier: workspace:* version: link:../../cellix/ui-core @@ -2274,25 +2279,25 @@ importers: version: link:../../cellix/config-vitest '@chromatic-com/storybook': specifier: ^5.2.1 - version: 5.2.1(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)) + version: 5.2.1(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0)) '@ocom-verification/archunit-tests': specifier: workspace:* version: link:../../ocom-verification/archunit-tests '@storybook/addon-a11y': specifier: 'catalog:' - version: 10.4.2(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)) + version: 10.4.2(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0)) '@storybook/addon-docs': specifier: 'catalog:' - version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) + version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) '@storybook/addon-vitest': specifier: 'catalog:' - version: 10.4.2(@vitest/browser-playwright@4.1.8)(@vitest/browser@4.1.8(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.8))(@vitest/runner@4.1.8)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(vitest@4.1.8) + version: 10.4.2(@vitest/browser-playwright@4.1.10)(@vitest/browser@4.1.10(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.10))(@vitest/runner@4.1.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vitest@4.1.10) '@storybook/react': specifier: ^10.4.2 - version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(typescript@6.0.3) + version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(typescript@6.0.3) '@storybook/react-vite': specifier: 'catalog:' - version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(typescript@6.0.3)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) + version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(typescript@6.0.3)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) '@types/react': specifier: ^19.1.11 version: 19.2.7 @@ -2304,16 +2309,16 @@ importers: version: 26.1.0 storybook: specifier: 'catalog:' - version: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0) typescript: specifier: 'catalog:' version: 6.0.3 vite: specifier: 8.0.16 - version: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + version: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/ocom/ui-community-route-root: dependencies: @@ -2344,25 +2349,25 @@ importers: version: link:../../cellix/config-vitest '@chromatic-com/storybook': specifier: ^5.2.1 - version: 5.2.1(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)) + version: 5.2.1(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0)) '@ocom-verification/archunit-tests': specifier: workspace:* version: link:../../ocom-verification/archunit-tests '@storybook/addon-a11y': specifier: 'catalog:' - version: 10.4.2(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)) + version: 10.4.2(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0)) '@storybook/addon-docs': specifier: 'catalog:' - version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) + version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) '@storybook/addon-vitest': specifier: 'catalog:' - version: 10.4.2(@vitest/browser-playwright@4.1.8)(@vitest/browser@4.1.8(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.8))(@vitest/runner@4.1.8)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(vitest@4.1.8) + version: 10.4.2(@vitest/browser-playwright@4.1.10)(@vitest/browser@4.1.10(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.10))(@vitest/runner@4.1.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vitest@4.1.10) '@storybook/react': specifier: 'catalog:' - version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(typescript@6.0.3) + version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(typescript@6.0.3) '@storybook/react-vite': specifier: 'catalog:' - version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(typescript@6.0.3)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) + version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(typescript@6.0.3)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) '@types/react': specifier: ^19.1.11 version: 19.2.7 @@ -2374,22 +2379,22 @@ importers: version: 26.1.0 storybook: specifier: 'catalog:' - version: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0) typescript: specifier: 'catalog:' version: 6.0.3 vite: specifier: 8.0.16 - version: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + version: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/ocom/ui-community-shared: dependencies: '@apollo/client': specifier: ^3.13.9 - version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@cellix/ui-core': specifier: workspace:* version: link:../../cellix/ui-core @@ -2426,22 +2431,22 @@ importers: version: link:../../cellix/config-vitest '@chromatic-com/storybook': specifier: ^5.2.1 - version: 5.2.1(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)) + version: 5.2.1(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0)) '@storybook/addon-a11y': specifier: 'catalog:' - version: 10.4.2(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)) + version: 10.4.2(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0)) '@storybook/addon-docs': specifier: 'catalog:' - version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) + version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) '@storybook/addon-vitest': specifier: 'catalog:' - version: 10.4.2(@vitest/browser-playwright@4.1.8)(@vitest/browser@4.1.8(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.8))(@vitest/runner@4.1.8)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(vitest@4.1.8) + version: 10.4.2(@vitest/browser-playwright@4.1.10)(@vitest/browser@4.1.10(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.10))(@vitest/runner@4.1.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vitest@4.1.10) '@storybook/react': specifier: 'catalog:' - version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(typescript@6.0.3) + version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(typescript@6.0.3) '@storybook/react-vite': specifier: 'catalog:' - version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(typescript@6.0.3)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) + version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(typescript@6.0.3)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) '@types/react': specifier: ^19.1.11 version: 19.2.7 @@ -2453,16 +2458,16 @@ importers: version: 26.1.0 storybook: specifier: 'catalog:' - version: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0) typescript: specifier: 'catalog:' version: 6.0.3 vite: specifier: 8.0.16 - version: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + version: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/ocom/ui-shared: dependencies: @@ -2471,7 +2476,7 @@ importers: version: 6.1.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@apollo/client': specifier: ^3.13.9 - version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@cellix/ui-core': specifier: workspace:* version: link:../../cellix/ui-core @@ -2508,25 +2513,25 @@ importers: version: link:../../cellix/config-vitest '@chromatic-com/storybook': specifier: ^5.2.1 - version: 5.2.1(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)) + version: 5.2.1(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0)) '@ocom-verification/archunit-tests': specifier: workspace:* version: link:../../ocom-verification/archunit-tests '@storybook/addon-a11y': specifier: 'catalog:' - version: 10.4.2(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)) + version: 10.4.2(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0)) '@storybook/addon-docs': specifier: 'catalog:' - version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) + version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) '@storybook/addon-vitest': specifier: 'catalog:' - version: 10.4.2(@vitest/browser-playwright@4.1.8)(@vitest/browser@4.1.8(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.8))(@vitest/runner@4.1.8)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(vitest@4.1.8) + version: 10.4.2(@vitest/browser-playwright@4.1.10)(@vitest/browser@4.1.10(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.10))(@vitest/runner@4.1.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vitest@4.1.10) '@storybook/react': specifier: 'catalog:' - version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(typescript@6.0.3) + version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(typescript@6.0.3) '@storybook/react-vite': specifier: 'catalog:' - version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(typescript@6.0.3)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) + version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(typescript@6.0.3)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) '@types/react': specifier: ^19.1.11 version: 19.2.7 @@ -2534,11 +2539,11 @@ importers: specifier: ^19.1.6 version: 19.2.3(@types/react@19.2.7) '@vitest/browser': - specifier: 4.1.8 - version: 4.1.8(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.8) + specifier: 4.1.10 + version: 4.1.10(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.10) '@vitest/coverage-istanbul': specifier: 'catalog:' - version: 4.1.8(vitest@4.1.8) + version: 4.1.10(vitest@4.1.10) jsdom: specifier: 'catalog:' version: 26.1.0 @@ -2547,19 +2552,19 @@ importers: version: 6.0.1 storybook: specifier: 'catalog:' - version: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0) storybook-addon-apollo-client: specifier: ^9.0.0 - version: 9.0.0(@apollo/client@3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(graphql@16.12.0)(react@19.2.0) + version: 9.0.0(@apollo/client@3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(graphql@16.12.0)(react@19.2.0) typescript: specifier: 'catalog:' version: 6.0.3 vite: specifier: 8.0.16 - version: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + version: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/ocom/ui-staff-route-community-management: dependencies: @@ -2599,10 +2604,10 @@ importers: version: 6.0.3 vite: specifier: 8.0.16 - version: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + version: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/ocom/ui-staff-route-finance: dependencies: @@ -2642,10 +2647,10 @@ importers: version: 6.0.3 vite: specifier: 8.0.16 - version: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + version: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/ocom/ui-staff-route-root: dependencies: @@ -2685,10 +2690,10 @@ importers: version: 6.0.3 vite: specifier: 8.0.16 - version: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + version: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/ocom/ui-staff-route-tech-admin: dependencies: @@ -2728,10 +2733,10 @@ importers: version: 6.0.3 vite: specifier: 8.0.16 - version: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + version: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/ocom/ui-staff-route-user-management: dependencies: @@ -2740,7 +2745,7 @@ importers: version: 6.1.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@apollo/client': specifier: ^3.13.9 - version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@graphql-typed-document-node/core': specifier: ^3.2.0 version: 3.2.0(graphql@16.12.0) @@ -2768,22 +2773,22 @@ importers: version: link:../../cellix/config-vitest '@chromatic-com/storybook': specifier: ^5.2.1 - version: 5.2.1(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)) + version: 5.2.1(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0)) '@storybook/addon-a11y': specifier: 'catalog:' - version: 10.4.2(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)) + version: 10.4.2(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0)) '@storybook/addon-docs': specifier: 'catalog:' - version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) + version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) '@storybook/addon-vitest': specifier: 'catalog:' - version: 10.4.2(@vitest/browser-playwright@4.1.8)(@vitest/browser@4.1.8(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.8))(@vitest/runner@4.1.8)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(vitest@4.1.8) + version: 10.4.2(@vitest/browser-playwright@4.1.10)(@vitest/browser@4.1.10(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.10))(@vitest/runner@4.1.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vitest@4.1.10) '@storybook/react': specifier: 'catalog:' - version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(typescript@6.0.3) + version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(typescript@6.0.3) '@storybook/react-vite': specifier: 'catalog:' - version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(typescript@6.0.3)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) + version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(typescript@6.0.3)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) '@types/react': specifier: ^19.1.11 version: 19.2.7 @@ -2795,16 +2800,16 @@ importers: version: 26.1.0 storybook: specifier: 'catalog:' - version: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0) typescript: specifier: 'catalog:' version: 6.0.3 vite: specifier: 8.0.16 - version: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + version: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages/ocom/ui-staff-shared: dependencies: @@ -2813,7 +2818,7 @@ importers: version: 6.1.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@apollo/client': specifier: ^3.13.9 - version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@cellix/ui-core': specifier: workspace:* version: link:../../cellix/ui-core @@ -2844,7 +2849,7 @@ importers: version: link:../../cellix/config-vitest '@storybook/react': specifier: 'catalog:' - version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(typescript@6.0.3) + version: 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(typescript@6.0.3) '@types/react': specifier: ^19.1.11 version: 19.2.7 @@ -2856,16 +2861,16 @@ importers: version: 26.1.0 storybook: specifier: 'catalog:' - version: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0) typescript: specifier: 'catalog:' version: 6.0.3 vite: specifier: 8.0.16 - version: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + version: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) vitest: specifier: 'catalog:' - version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) packages: @@ -3909,6 +3914,10 @@ packages: resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} engines: {node: '>=6.9.0'} + '@babel/runtime@7.29.7': + resolution: {integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==} + engines: {node: '>=6.9.0'} + '@babel/template@7.27.2': resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} engines: {node: '>=6.9.0'} @@ -4622,18 +4631,27 @@ packages: '@emnapi/core@1.10.0': resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} + '@emnapi/core@1.11.2': + resolution: {integrity: sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA==} + '@emnapi/core@1.9.2': resolution: {integrity: sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==} '@emnapi/runtime@1.10.0': resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} + '@emnapi/runtime@1.11.2': + resolution: {integrity: sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==} + '@emnapi/runtime@1.9.2': resolution: {integrity: sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==} '@emnapi/wasi-threads@1.2.1': resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} + '@emnapi/wasi-threads@1.2.2': + resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==} + '@emotion/hash@0.8.0': resolution: {integrity: sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==} @@ -5234,8 +5252,8 @@ packages: '@emnapi/core': ^1.7.1 '@emnapi/runtime': ^1.7.1 - '@napi-rs/wasm-runtime@1.1.4': - resolution: {integrity: sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==} + '@napi-rs/wasm-runtime@1.1.6': + resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==} peerDependencies: '@emnapi/core': ^1.7.1 '@emnapi/runtime': ^1.7.1 @@ -5312,6 +5330,12 @@ packages: peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' + '@opentelemetry/core@2.9.0': + resolution: {integrity: sha512-m2nckMT80NnmjTYSPjJQObBJ+8dgkoajEOUbznL8AHZ3T3yHRk2P7gI1PhEBc1+lOnrYE9UWrWHqJDsmqjmNbw==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + '@opentelemetry/exporter-logs-otlp-grpc@0.57.2': resolution: {integrity: sha512-eovEy10n3umjKJl2Ey6TLzikPE+W4cUQ4gCwgGP1RqzTGtgDra0WjIqdy29ohiUKfvmbiL3MndZww58xfIvyFw==} engines: {node: '>=14'} @@ -5444,9 +5468,9 @@ packages: peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' - '@opentelemetry/propagator-jaeger@1.30.1': - resolution: {integrity: sha512-Pj/BfnYEKIOImirH76M4hDaBSx6HyZ2CXUqk+Kj02m6BB80c/yo4BdWkn/1gDFfU+YPY+bPR2U0DKBfdxCKwmg==} - engines: {node: '>=14'} + '@opentelemetry/propagator-jaeger@2.9.0': + resolution: {integrity: sha512-4mYGty27rYvSM0jtp1ZUOqd3LfVRCYg9H5G9OFzSx5HViYToU21MFhWfco7x1HwXr7ER8yGOiCIHZUwjPksc0Q==} + engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' @@ -5799,8 +5823,8 @@ packages: cpu: [arm] os: [android] - '@oxc-resolver/binding-android-arm-eabi@11.20.0': - resolution: {integrity: sha512-IjfWOXRgJFNdORDl+Uf1aibNgZY2guOD3zmOhx1BGVb/MIiqlFTdmjpQNplSN58lhWehnX4UNqC3QwpUo8pjJg==} + '@oxc-resolver/binding-android-arm-eabi@11.24.2': + resolution: {integrity: sha512-y09e0L0SRI2OA2tUIrjBgoV3eH5hvUKXNkJqXmNo5V2WxIjyC7I7aJfRLMEVpA8yi95f90gFDvO0VMgrDw+vwA==} cpu: [arm] os: [android] @@ -5809,8 +5833,8 @@ packages: cpu: [arm64] os: [android] - '@oxc-resolver/binding-android-arm64@11.20.0': - resolution: {integrity: sha512-QqslZAuFQG8Q9xm7JuIn8JUbvywhSBMVhuQHtYW+auirZJloS41oxUUaBXk7uUhZJgp44c5zQLeVvmFaDQB+2Q==} + '@oxc-resolver/binding-android-arm64@11.24.2': + resolution: {integrity: sha512-cl4icWaZFnLdg8m6qtnh5rBMuGbxc/ptStFHLeCNwr+2cZjkjNwQu/jYRS0CHlnPecOJMpuS5M6/BH+0J/YkEg==} cpu: [arm64] os: [android] @@ -5819,8 +5843,8 @@ packages: cpu: [arm64] os: [darwin] - '@oxc-resolver/binding-darwin-arm64@11.20.0': - resolution: {integrity: sha512-MUcavykj2ewlR+kc5arpg4tC2RvzJkUxWtNv74pf7lcNk00GpIpN43vXMj+j6r4eMmfZhlb8hueKoIb8e9kAGQ==} + '@oxc-resolver/binding-darwin-arm64@11.24.2': + resolution: {integrity: sha512-At29QEMF6HajbQvgY8K6OXnHD1x9rad74xBEfmCB6ZqCGsdq75aK7tOYcTbOanMy8qdIBrfL3SMr3p/lfSlb9w==} cpu: [arm64] os: [darwin] @@ -5829,8 +5853,8 @@ packages: cpu: [x64] os: [darwin] - '@oxc-resolver/binding-darwin-x64@11.20.0': - resolution: {integrity: sha512-BGB16nRUK5Etiv//ihPyzj8Lj1px0mhh4YIfe0FDf045ywknfSm0GEbiRESpr6Q4K82AvnyaRIhhluHByvS4bg==} + '@oxc-resolver/binding-darwin-x64@11.24.2': + resolution: {integrity: sha512-A5Kqr1EUj4oIL5CF4WRssq/o5P0Y11cwoFouMRmQ7YnC/A8V93nv1nb7aSU8HwcgmXropjLNkVTl4MN87cu28Q==} cpu: [x64] os: [darwin] @@ -5839,8 +5863,8 @@ packages: cpu: [x64] os: [freebsd] - '@oxc-resolver/binding-freebsd-x64@11.20.0': - resolution: {integrity: sha512-JZgtePaqj3qmD5XFHJaSLWzHRxQu0LaPkdoM1KJXYADvAaa83ijXHclV3ej3CueeW0wxfIAbGCZVP45J0CA7uQ==} + '@oxc-resolver/binding-freebsd-x64@11.24.2': + resolution: {integrity: sha512-R5xkRBRRz7ceH/P5Jrc6G7FmdUdgpLYyESFAUDVTNQ9K0sGPxcp4ljiwEwEqsvNcQ4sYbMRrWcHHBCu7ksAJVw==} cpu: [x64] os: [freebsd] @@ -5849,8 +5873,8 @@ packages: cpu: [arm] os: [linux] - '@oxc-resolver/binding-linux-arm-gnueabihf@11.20.0': - resolution: {integrity: sha512-hOQ/p3ry3v3SchUBXicrrnszaI/UmYzM4wtS4RGfwgVUX7a+HbyQSzJ5aOzu+o6XZkFkS3ZXN4PZAzhOb77OSg==} + '@oxc-resolver/binding-linux-arm-gnueabihf@11.24.2': + resolution: {integrity: sha512-k/RuYL4L/R58IBn3wT5ma3Wh4k62bp1eYCFRWCmMsasUOqL+H6sW0VGFadEzKWXFFlz+2uIMoeMk9ySSZJHgbg==} cpu: [arm] os: [linux] @@ -5859,8 +5883,8 @@ packages: cpu: [arm] os: [linux] - '@oxc-resolver/binding-linux-arm-musleabihf@11.20.0': - resolution: {integrity: sha512-2ArPksaw0AqeuGBfoS715VF+JvJQAhD2niWgjE5hVO+L+nAfikVQopvngCMX9x4BD8itWoQ3dnikrQyl5Ho5Jg==} + '@oxc-resolver/binding-linux-arm-musleabihf@11.24.2': + resolution: {integrity: sha512-bnHAak3ujYfH5pKk4NieFNbvYvernfoQDgwLddbZ3OtMYrem87/qjlA+u+aKG0oZcqSLGCful/6/CEA+aeAgaA==} cpu: [arm] os: [linux] @@ -5870,8 +5894,8 @@ packages: os: [linux] libc: [glibc] - '@oxc-resolver/binding-linux-arm64-gnu@11.20.0': - resolution: {integrity: sha512-0bJnmYFp62JdZ4nVMDUZ/C58BCZOCcqgKtnUlp7L9Ojf/czIN+3j72YlLPeWLkzlr6SlYvIQA4SGV/HyO0d+qg==} + '@oxc-resolver/binding-linux-arm64-gnu@11.24.2': + resolution: {integrity: sha512-vDT3KHgzYp47gmtNOqL2VNhCyl5Zv643eyxm//A68J8DeUGXrvD1pZFiaT4jSfe+RInfnn1R2yVHye4enx6RnA==} cpu: [arm64] os: [linux] libc: [glibc] @@ -5882,8 +5906,8 @@ packages: os: [linux] libc: [musl] - '@oxc-resolver/binding-linux-arm64-musl@11.20.0': - resolution: {integrity: sha512-wKHHzPKZo7Ufhv/Bt6yxT7FOgnIgW4gwXcJUipkShGp68W3wGVqvr1Sr0fY65lN0Oy6y41+g2kIDvkgZaMMUkw==} + '@oxc-resolver/binding-linux-arm64-musl@11.24.2': + resolution: {integrity: sha512-+kMlQvbzfyEYtu5FcjE4p+ttBLpKW4d/AsAsuE69BxV6V4twZJeIQZFfD8gh/wqglY0MkPSezWXQH0jBV13MUw==} cpu: [arm64] os: [linux] libc: [musl] @@ -5894,8 +5918,8 @@ packages: os: [linux] libc: [glibc] - '@oxc-resolver/binding-linux-ppc64-gnu@11.20.0': - resolution: {integrity: sha512-RN8goF7Ie0B79L4i4G6OeBocTgSC56vJbQ65VJje+oXnldVpLnOU7j/AQ/dP94TcCS+Yh6WG8u3Qt4ETteXFNQ==} + '@oxc-resolver/binding-linux-ppc64-gnu@11.24.2': + resolution: {integrity: sha512-shjfMhmZ3gq9fv/w7bi3PnZlgOPG+2QAOFf0BJF0EgBSIGZ6PMLN2zbGEblTUYB/NKVDRyYhE2ff3dJ1QqNPkA==} cpu: [ppc64] os: [linux] libc: [glibc] @@ -5906,8 +5930,8 @@ packages: os: [linux] libc: [glibc] - '@oxc-resolver/binding-linux-riscv64-gnu@11.20.0': - resolution: {integrity: sha512-5l1yU6/xQEqLZRzxqmMxJfWPslpwCmBsdDGaBvABPehxquCXDC7dd7oraNdKSJUMDXSM7VvVj8H2D2FTjU7oWw==} + '@oxc-resolver/binding-linux-riscv64-gnu@11.24.2': + resolution: {integrity: sha512-zGelwFR5oRo+b69k8Lrzun86DyUHzfKN6cnjbR9l7Z7NIRznOE/2ZvPa1IUKqAL2PzAXOdwkfVqNvO1H2RlpAw==} cpu: [riscv64] os: [linux] libc: [glibc] @@ -5918,8 +5942,8 @@ packages: os: [linux] libc: [musl] - '@oxc-resolver/binding-linux-riscv64-musl@11.20.0': - resolution: {integrity: sha512-xHEvkbgz6UC+A3JOyDQy76LkUaxsNSfIr3/GV8slwZsnuooJiIB34gzJfsyvR4JdCYNUUPsRJc/w/oWkODu+hg==} + '@oxc-resolver/binding-linux-riscv64-musl@11.24.2': + resolution: {integrity: sha512-qxZ1SWCXJY0eyhAlP6Lmo9F2Nrtx7EkYj9oCgL8apDPCwXwCEDA2U697bbT81JIc2IrVjxO4KX6WU2N+oN9Z4w==} cpu: [riscv64] os: [linux] libc: [musl] @@ -5930,8 +5954,8 @@ packages: os: [linux] libc: [glibc] - '@oxc-resolver/binding-linux-s390x-gnu@11.20.0': - resolution: {integrity: sha512-aWPDUUmSeyHvlW+SoEUd+JIJsQhVhu6a5tBpDRMu058naPAchTgAVGCFy35zjbnFlt0i8hLWziff6HX0D3LU4g==} + '@oxc-resolver/binding-linux-s390x-gnu@11.24.2': + resolution: {integrity: sha512-sGCecF3cx2DFlH4t/z7ApnOnXqN48p5p5mlHDEnHTAukQa2P+qMVE4CwyWE9W+q/m3QJ7kKfGrIjax31f44oFQ==} cpu: [s390x] os: [linux] libc: [glibc] @@ -5942,8 +5966,8 @@ packages: os: [linux] libc: [glibc] - '@oxc-resolver/binding-linux-x64-gnu@11.20.0': - resolution: {integrity: sha512-x2YeSimvhJjKLVD8KSu8f/rqU1potcdEMkApIPJqjZWN7c2Fpt4g2X32WDg1p+XDAmyT7nuQGe0vnhvXeLbH+g==} + '@oxc-resolver/binding-linux-x64-gnu@11.24.2': + resolution: {integrity: sha512-k/VlMMcSzMlahb3/fENM4rTlsJ0s3fFROA0KXPBmKggqmTSaE383sl8F3KCOXPLmVsYfW6hCitMhXCEtNeZxxg==} cpu: [x64] os: [linux] libc: [glibc] @@ -5954,14 +5978,14 @@ packages: os: [linux] libc: [musl] - '@oxc-resolver/binding-linux-x64-musl@11.20.0': - resolution: {integrity: sha512-kcRLEIxpZefeYfLChjpgFf3ilBzRDZ+yobMrpRsQlSrxuFGtm3U6PMU7AaEpMqo3NfDGVyJJseAjnRLzMFHjwQ==} + '@oxc-resolver/binding-linux-x64-musl@11.24.2': + resolution: {integrity: sha512-8hbnZyNi97b/8wapYaIF9+t9GmZKBW2vunaOc3h9HGJptH7b7XpvZqOTBSm/MpTjr7H497BlgOaSfLUdhmy2bw==} cpu: [x64] os: [linux] libc: [musl] - '@oxc-resolver/binding-openharmony-arm64@11.20.0': - resolution: {integrity: sha512-HHcfnApSZGtKhTiHqe8OZruOZe5XuFQH5/E0Yhj3u8fnFvzkM4/k6WjacUf4SvA0SPEAbfbgYmVPuo0VX/fIBQ==} + '@oxc-resolver/binding-openharmony-arm64@11.24.2': + resolution: {integrity: sha512-MvyGik3a6pVgZ0t/kWlbmFxFLmXQJwgLsY2eYFHLpy0wGwRbfzeIGgDwQ3kXqE30z+kSXennRkCrT7TUvkptNg==} cpu: [arm64] os: [openharmony] @@ -5970,8 +5994,8 @@ packages: engines: {node: '>=14.0.0'} cpu: [wasm32] - '@oxc-resolver/binding-wasm32-wasi@11.20.0': - resolution: {integrity: sha512-Tn0y1XOFYHNfK1wp1Z5QK8Rcld/bsOwRISQXfqAZ5IBpv8Gz1IvV39fUWNprqNdRizgcvFhOzWwFun2zkJsyBg==} + '@oxc-resolver/binding-wasm32-wasi@11.24.2': + resolution: {integrity: sha512-vHcssMPwO08RTvj/c0iOBz90attxyG3wQJ0dTcyEQK43LRpcdLWZlV5feBhv6Isn6ahbQIzHbCgfa81+RiML0Q==} engines: {node: '>=14.0.0'} cpu: [wasm32] @@ -5980,8 +6004,8 @@ packages: cpu: [arm64] os: [win32] - '@oxc-resolver/binding-win32-arm64-msvc@11.20.0': - resolution: {integrity: sha512-qPi25YNPe4YenS8MgsQU2+bIFHxxpLx1LVna2444cEHqNPhNjvWf9zqj4aWE43H9LpAsTmkkAlA3eL5ElBU3mA==} + '@oxc-resolver/binding-win32-arm64-msvc@11.24.2': + resolution: {integrity: sha512-uokJqro2iBqkFvJdKQLP7d8/BUmFwESQFVmIJUQKj1Xn1a/LysJoe1vmeECLF5b3jsV8CAL5sEMJXX6SdK9Nhg==} cpu: [arm64] os: [win32] @@ -5995,8 +6019,8 @@ packages: cpu: [x64] os: [win32] - '@oxc-resolver/binding-win32-x64-msvc@11.20.0': - resolution: {integrity: sha512-Wb14jWEW8huH6It9F6sXd9vrYmIS7pMrgkU6sxpLxkP+9z+wRgs71hUEhRpcn8FOXAFa27FVWfY2tRpbfTzfLw==} + '@oxc-resolver/binding-win32-x64-msvc@11.24.2': + resolution: {integrity: sha512-UqGPmo56KDfLlfXFAFIrNflHT8tFxWGEivWg3Zeyp4Uy2NlKN1FGPr6/BxcLGG3+kZ6Wp14g5Uj+n71boqZfiw==} cpu: [x64] os: [win32] @@ -6807,8 +6831,8 @@ packages: '@storybook/addon-vitest@10.4.2': resolution: {integrity: sha512-gq1ZVr0IOLgiS2PzaJqHxKLczwrXvA5g3W2k/FVJA19fJNFNUut1IyQCQRSJTXLLXbnNaa8I0wjGGc2BoLarJg==} peerDependencies: - '@vitest/browser': 4.1.8 - '@vitest/browser-playwright': 4.1.8 + '@vitest/browser': 4.1.10 + '@vitest/browser-playwright': 4.1.10 '@vitest/runner': ^3.0.0 || ^4.0.0 storybook: ^10.4.2 vitest: ^3.0.0 || ^4.0.0 @@ -6855,6 +6879,11 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + '@storybook/icons@2.1.0': + resolution: {integrity: sha512-Fxh9vYpX9bQqFeHRiY8h2ApeRGDzRSMLwJwNZ/AIRqnyOKHxRKL+yFe+ctEkVJmuptRE9u1Hrn8ZZNHyfDKKNg==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + '@storybook/react-dom-shim@10.4.2': resolution: {integrity: sha512-Eng3Yt2NCjPX94QcfyLeUFhrMj0hec2yU9J/qafBVbfj9XrFI8o+0ZwYJ7uXb9ECbvPN4y06dgt/2W/LiR417w==} peerDependencies: @@ -7051,6 +7080,9 @@ packages: '@tybys/wasm-util@0.10.1': resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + '@tybys/wasm-util@0.10.3': + resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==} + '@types/aria-query@5.0.4': resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} @@ -7102,6 +7134,9 @@ packages: '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + '@types/express-serve-static-core@4.19.7': resolution: {integrity: sha512-FvPtiIf1LfhzsaIXhv/PHan/2FeQBbtBDtfX2QfvPxdUelMDEckK08SM6nqo1MIZY3RUlfA+HV8+hFUSio78qg==} @@ -7177,6 +7212,9 @@ packages: '@types/node@24.10.1': resolution: {integrity: sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==} + '@types/node@26.1.1': + resolution: {integrity: sha512-nxAkRSVkN1Y0JC1W8ky/fTfkGsMmcrRsbx+3XoZE+rMOX71kLYTV7fLXpqud1GpbpP5TuffXFqfX7fH2GgZREw==} + '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} @@ -7352,30 +7390,30 @@ packages: babel-plugin-react-compiler: optional: true - '@vitest/browser-playwright@4.1.8': - resolution: {integrity: sha512-SR7FqgegaexEg73xvf3ArtygXegagMdXnL0EZMpxrWvvhQxvicD/E8p0ib0J91riPRtQUViyh67Xjw3NqvyhVg==} + '@vitest/browser-playwright@4.1.10': + resolution: {integrity: sha512-nMoXGEiRpT7m3W7NsbvrM2aKNwiNHZf+zEpUCvMteGjZFvfT96Q9fh7QyB98dvDWXiKvrLxA7bJ1mCOOv+JQPw==} peerDependencies: playwright: 1.59.0 - vitest: 4.1.8 + vitest: 4.1.10 - '@vitest/browser@4.1.8': - resolution: {integrity: sha512-u21VzX07HzlJYpFgkxmjEXar/tG2UqWGgyGG/46SrrPc7rSdCTPw5vuowopO9CIqF8UCUQzDFdbVnNpw6N0BfQ==} + '@vitest/browser@4.1.10': + resolution: {integrity: sha512-UDwuWGwXj646CBx/bQHOaJSX7np0I8JL/UKQYa1e4QrVHH8VdWtx8eaOuf8sy0ShwDgR6NjJAsp5eF6vjF6qng==} peerDependencies: - vitest: 4.1.8 + vitest: 4.1.10 - '@vitest/coverage-istanbul@4.1.8': - resolution: {integrity: sha512-/h514nMZMKI6foh21mVgO1zlCH6pdDamwKMbla1uLU2GMxTlfp0PQMxovWozmzQdCIQYZ2XXEzg2zNZom2zAOg==} + '@vitest/coverage-istanbul@4.1.10': + resolution: {integrity: sha512-AyNJ5pQRFqCX7pwB9PSTmoVKPaZ4H5IEVJfJsT+q1DYkXvZMEFYgJlyk5sfStmt9rVYRyYYRRsuBeImCOc39ww==} peerDependencies: - vitest: 4.1.8 + vitest: 4.1.10 '@vitest/expect@3.2.4': resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==} - '@vitest/expect@4.1.8': - resolution: {integrity: sha512-h3nDO677RDLEGlBxyQ5CW8RlMThSKSRLUePLOx09gNIWRL40edgA1GCZSZgf1W55MFAG6/Sw14KeaAnqv0NKdQ==} + '@vitest/expect@4.1.10': + resolution: {integrity: sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==} - '@vitest/mocker@4.1.8': - resolution: {integrity: sha512-LEiN/xe4OSIbKe9HQIp5OC24agGD9J5CnmMgsLohVVoOPWL9a2sBoR6VBx43jQZb7Kr1l4RCuyCJzcAa0+dojw==} + '@vitest/mocker@4.1.10': + resolution: {integrity: sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==} peerDependencies: msw: ^2.4.9 vite: 8.0.16 @@ -7388,26 +7426,26 @@ packages: '@vitest/pretty-format@3.2.4': resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==} - '@vitest/pretty-format@4.1.8': - resolution: {integrity: sha512-9GasEBxpZ1VYIpqHf/0+YGg121uSNwCKOJqIrTwWP/TB7DmFCiaBpNl3aPZzoLWfWkuqhbH8vJIVobZkvdo2cA==} + '@vitest/pretty-format@4.1.10': + resolution: {integrity: sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==} - '@vitest/runner@4.1.8': - resolution: {integrity: sha512-EmVxeBAfMJvycdjd6Hm+RbFBbA9fKvo0Kx37hNpBYoYeavH3RNsBXWDooR1mgD52dCrxIIuP7UotpfiwOikvcg==} + '@vitest/runner@4.1.10': + resolution: {integrity: sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==} - '@vitest/snapshot@4.1.8': - resolution: {integrity: sha512-acfZboRmAIf05DEKcBQy33VXojFJjtUdLyo7oOmV9kebb2xdU01UknNiPuPZoJZQyO7DF0gZdTGTpeAzET9QPQ==} + '@vitest/snapshot@4.1.10': + resolution: {integrity: sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==} '@vitest/spy@3.2.4': resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==} - '@vitest/spy@4.1.8': - resolution: {integrity: sha512-6EevtBp6OZOPF7bmz36HrGMeP3txgVSrgebWxHOafDXGkhIzfXK14f8KF6MuFfgXXUeHxmpD3BQxkV00/3s5mA==} + '@vitest/spy@4.1.10': + resolution: {integrity: sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==} '@vitest/utils@3.2.4': resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==} - '@vitest/utils@4.1.8': - resolution: {integrity: sha512-uOJamYALNhfJ6iolExyQM40yIQwDqYnkKtQ5VCiSe17E33H0aQ/u+1GlRuz4LZBk6Mm3sg90G9hEbmEt37C1Zg==} + '@vitest/utils@4.1.10': + resolution: {integrity: sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==} '@webassemblyjs/ast@1.14.1': resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==} @@ -7533,6 +7571,11 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + acorn@8.17.0: + resolution: {integrity: sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==} + engines: {node: '>=0.4.0'} + hasBin: true + address@1.2.2: resolution: {integrity: sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==} engines: {node: '>= 10.0.0'} @@ -7541,6 +7584,10 @@ packages: resolution: {integrity: sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==} engines: {node: '>=12.0'} + agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + agent-base@7.1.4: resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} engines: {node: '>= 14'} @@ -7579,6 +7626,9 @@ packages: ajv@8.18.0: resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} + ajv@8.20.0: + resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} + algoliasearch-helper@3.26.1: resolution: {integrity: sha512-CAlCxm4fYBXtvc5MamDzP6Svu8rW4z9me4DCBY1rQ2UDJ0u0flWmusQ8M3nOExZsLLRcUwUPoRAPMrhzOG3erw==} peerDependencies: @@ -7783,8 +7833,8 @@ packages: resolution: {integrity: sha512-ilYanEU8vxxBexpJd8cWM4ElSQq4QctCLKih0TSfjIfCQTeyH/6zVrmIJfLPrKTKJRbiG+cfnZbQIjAlJmF1jQ==} engines: {node: '>=4'} - axios@1.16.0: - resolution: {integrity: sha512-6hp5CwvTPlN2A31g5dxnwAX0orzM7pmCRDLnZSX772mv8WDqICwFjowHuPs04Mc8deIld1+ejhtaMn5vp6b+1w==} + axios@1.18.0: + resolution: {integrity: sha512-E32NzpYKp++W7XRe52rHiXV2ehxmh3wbdgO7MHeFM+vqxLBYHzt0ElkiImtOBxtOmyp0yoC8C6uESVV84Y2/hw==} azurite@3.35.0: resolution: {integrity: sha512-GzKmi+/5U0baNRjEEVtBMLpLuIKEJ0uSh0VWBzOI4qe4f5ziJyoZQmcTO7QhxZTF6+rphj7TZS3PtJY7uiiacA==} @@ -7850,6 +7900,11 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + baseline-browser-mapping@2.10.43: + resolution: {integrity: sha512-AjYpR78kDWAY3Efj+cDTFH9t9SCoL7OoTp1BOb0mQV7S+6CiLwnWM3FyxhJtdPufDFKzmCSFoUncKjWgJEZTCQ==} + engines: {node: '>=6.0.0'} + hasBin: true + basic-auth@2.0.1: resolution: {integrity: sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==} engines: {node: '>= 0.8'} @@ -7940,6 +7995,11 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true + browserslist@4.28.6: + resolution: {integrity: sha512-FQBYNK15VMslhLHpA7+n+n1GOlF1kId2xcCg7/j95f24AOF6VDYMNH4mFxF7KuaTdv627faazpOAjFzMrfJOUw==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + bser@2.1.1: resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} @@ -8061,6 +8121,9 @@ packages: caniuse-lite@1.0.30001777: resolution: {integrity: sha512-tmN+fJxroPndC74efCdp12j+0rk0RHwV5Jwa1zWaFVyw2ZxAuPeG8ZgWC3Wz7uSjT3qMRQ5XHZ4COgQmsCMJAQ==} + caniuse-lite@1.0.30001806: + resolution: {integrity: sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==} + capital-case@1.0.4: resolution: {integrity: sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==} @@ -8112,8 +8175,8 @@ packages: chardet@2.1.1: resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==} - check-error@2.1.1: - resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} + check-error@2.1.3: + resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} engines: {node: '>= 16'} cheerio-select@2.1.0: @@ -8663,8 +8726,8 @@ packages: resolution: {integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==} engines: {node: '>=18'} - default-browser@5.4.0: - resolution: {integrity: sha512-XDuvSq38Hr1MdN47EDvYtx3U0MTqpCEn+F6ft8z2vYDzMrvQhVp0ui9oQdqW3MvK3vqUETglt1tVGgjLuJ5izg==} + default-browser@5.5.0: + resolution: {integrity: sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==} engines: {node: '>=18'} defaults@1.0.4: @@ -8859,6 +8922,9 @@ packages: electron-to-chromium@1.5.307: resolution: {integrity: sha512-5z3uFKBWjiNR44nFcYdkcXjKMbg5KXNdciu7mhTPo9tB7NbqSNP2sSnGR+fqknZSCwKkBN+oxiiajWs4dT6ORg==} + electron-to-chromium@1.5.393: + resolution: {integrity: sha512-kiDJdIUawuEIcp9XoICKp1iTYDEbgguIPq526N1Q7jIQDeQ3CqoMx71025PI/7E48Ddtw2HuWsVjY7afEgNxmg==} + elliptic@6.6.1: resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==} @@ -8896,8 +8962,8 @@ packages: resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} engines: {node: '>= 0.8'} - enhanced-resolve@5.20.0: - resolution: {integrity: sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==} + enhanced-resolve@5.24.3: + resolution: {integrity: sha512-PwKooW9JUzh5chmYfHM3IQl5OkK2u2Nm011MgeZrss3JmFraUx/fqrf78kk8GUMYoibx/14MdwTl/1WKkG7TpQ==} engines: {node: '>=10.13.0'} entities@2.2.0: @@ -8944,10 +9010,17 @@ packages: es-module-lexer@2.0.0: resolution: {integrity: sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==} + es-module-lexer@2.3.1: + resolution: {integrity: sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==} + es-object-atoms@1.1.1: resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} engines: {node: '>= 0.4'} + es-object-atoms@1.1.2: + resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} + engines: {node: '>= 0.4'} + es-set-tostringtag@2.1.0: resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} engines: {node: '>= 0.4'} @@ -9124,8 +9197,8 @@ packages: fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - fast-uri@4.0.1: - resolution: {integrity: sha512-j0VntHrljgRKiWdbjL1xECG44OQu5sb7en4b8z2CcRvtDUEG5DAvkXlllrRhvbABR+m2mUiSgYBPvDj/PzB0dg==} + fast-uri@4.1.1: + resolution: {integrity: sha512-YPOs1zD5TG2+EZt+r88LwF6mclA7TPkpwMP7ZN3TO2HiHS8TXvq7QA/17iJsV9dubcLo/f8eEYqMBruyQV21hQ==} fast-xml-builder@1.2.0: resolution: {integrity: sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q==} @@ -9362,8 +9435,8 @@ packages: resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} engines: {node: '>= 0.4'} - get-tsconfig@4.13.0: - resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==} + get-tsconfig@4.14.0: + resolution: {integrity: sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==} github-slugger@1.5.0: resolution: {integrity: sha512-wIh+gKBI9Nshz2o46B0B3f5k/W+WI9ZAv6y5Dn5WJ5SK1t0TnDimB4WE5rmTD05ZAIn8HALCZVmCsvj0w0v0lw==} @@ -9492,7 +9565,7 @@ packages: crossws: ~0.3 graphql: ^15.10.1 || ^16 uWebSockets.js: ^20 - ws: 8.21.0 + ws: 8.21.1 peerDependenciesMeta: '@fastify/websocket': optional: true @@ -9714,6 +9787,10 @@ packages: https-browserify@1.0.0: resolution: {integrity: sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==} + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + https-proxy-agent@7.0.6: resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} engines: {node: '>= 14'} @@ -10114,8 +10191,8 @@ packages: resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} engines: {node: '>=8'} - is-wsl@3.1.0: - resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} + is-wsl@3.1.1: + resolution: {integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==} engines: {node: '>=16'} is-yarn-global@0.4.1: @@ -10149,7 +10226,7 @@ packages: isomorphic-ws@5.0.0: resolution: {integrity: sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==} peerDependencies: - ws: 8.21.0 + ws: 8.21.1 istanbul-lib-coverage@3.2.2: resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} @@ -10338,78 +10415,78 @@ packages: lie@3.1.1: resolution: {integrity: sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==} - lightningcss-android-arm64@1.32.0: - resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + lightningcss-android-arm64@1.33.0: + resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [android] - lightningcss-darwin-arm64@1.32.0: - resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + lightningcss-darwin-arm64@1.33.0: + resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [darwin] - lightningcss-darwin-x64@1.32.0: - resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + lightningcss-darwin-x64@1.33.0: + resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [darwin] - lightningcss-freebsd-x64@1.32.0: - resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + lightningcss-freebsd-x64@1.33.0: + resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [freebsd] - lightningcss-linux-arm-gnueabihf@1.32.0: - resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + lightningcss-linux-arm-gnueabihf@1.33.0: + resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==} engines: {node: '>= 12.0.0'} cpu: [arm] os: [linux] - lightningcss-linux-arm64-gnu@1.32.0: - resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + lightningcss-linux-arm64-gnu@1.33.0: + resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] libc: [glibc] - lightningcss-linux-arm64-musl@1.32.0: - resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + lightningcss-linux-arm64-musl@1.33.0: + resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] libc: [musl] - lightningcss-linux-x64-gnu@1.32.0: - resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + lightningcss-linux-x64-gnu@1.33.0: + resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] libc: [glibc] - lightningcss-linux-x64-musl@1.32.0: - resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + lightningcss-linux-x64-musl@1.33.0: + resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] libc: [musl] - lightningcss-win32-arm64-msvc@1.32.0: - resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + lightningcss-win32-arm64-msvc@1.33.0: + resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [win32] - lightningcss-win32-x64-msvc@1.32.0: - resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + lightningcss-win32-x64-msvc@1.33.0: + resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [win32] - lightningcss@1.32.0: - resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + lightningcss@1.33.0: + resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==} engines: {node: '>= 12.0.0'} lilconfig@3.1.3: @@ -10428,8 +10505,8 @@ packages: enquirer: optional: true - loader-runner@4.3.1: - resolution: {integrity: sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==} + loader-runner@4.3.2: + resolution: {integrity: sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==} engines: {node: '>=6.11.5'} loader-utils@2.0.4: @@ -11065,16 +11142,16 @@ packages: resolution: {integrity: sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==} engines: {node: '>=12.0.0'} - nanoid@3.3.11: - resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + nanoid@3.3.16: + resolution: {integrity: sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true native-duplexpair@1.0.0: resolution: {integrity: sha512-E7QQoM+3jvNtlmyfqRZ0/U75VFgCls+fSkbml2MpgWkWyz3ox8Y58gNhfuziuQYGNNQAbFZJQck55LHCnCK6CA==} - needle@3.3.1: - resolution: {integrity: sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==} + needle@3.5.0: + resolution: {integrity: sha512-jaQyPKKk2YokHrEg+vFDYxXIHTCBgiZwSHOoVx/8V3GIBS8/VN6NdVRmg8q1ERtPkMvmOvebsgga4sAj5hls/w==} engines: {node: '>= 4.4.x'} hasBin: true @@ -11138,6 +11215,10 @@ packages: node-releases@2.0.27: resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} + node-releases@2.0.51: + resolution: {integrity: sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==} + engines: {node: '>=18'} + node-stdlib-browser@1.3.1: resolution: {integrity: sha512-X75ZN8DCLftGM5iKwoYLA3rjnrAEs97MkzvSd4q2746Tgpg8b8XWiBGiBG4ZpgcAqBgtgPHTiAc8ZMCvZuikDw==} engines: {node: '>=10'} @@ -11189,8 +11270,8 @@ packages: nullthrows@1.1.1: resolution: {integrity: sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==} - nwsapi@2.2.22: - resolution: {integrity: sha512-ujSMe1OWVn55euT1ihwCI1ZcAaAU3nxUiDwfDQldc51ZXaB9m2AyOn6/jh1BLe2t/G8xd6uKG1UBF2aZJeg2SQ==} + nwsapi@2.2.24: + resolution: {integrity: sha512-7YRhZ3jS45LwmSCT4b2sVFHt/WuovaktDU07QrtOBY2PXskss5a9jfmR9jptyumwXST+rFjrmppMY1KT/yn35A==} object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} @@ -11285,8 +11366,8 @@ packages: oxc-resolver@11.14.0: resolution: {integrity: sha512-i4wNrqhOd+4YdHJfHglHtFiqqSxXuzFA+RUqmmWN1aMD3r1HqUSrIhw17tSO4jwKfhLs9uw1wzFPmvMsWacStg==} - oxc-resolver@11.20.0: - resolution: {integrity: sha512-CblytBiV/a/ZXY34dsVU2NxhIOxMXst8CvDCtyBelVITgd7PLrKzbEbA6oKLdPjvDKDzCiW48qzmzZ+mYaqn+g==} + oxc-resolver@11.24.2: + resolution: {integrity: sha512-FY91FiDBj7ls5MsFS9jN3tjz2o0/zsdSsymlakySaBwVJZorHhkWyICLZMKxlu1R9vYo+sd3z1jwb4J8x7bNDw==} p-cancelable@3.0.0: resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==} @@ -11506,6 +11587,10 @@ packages: resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} engines: {node: '>=12'} + picomatch@4.0.5: + resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} + engines: {node: '>=12'} + pify@2.3.0: resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} engines: {node: '>=0.10.0'} @@ -12255,8 +12340,8 @@ packages: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} - recast@0.23.11: - resolution: {integrity: sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==} + recast@0.23.12: + resolution: {integrity: sha512-dEWRjcINDu/F4l2dYx57ugBtD7HV9KXESyxhzw/MqWLeglJrsjJKqACPyUPg+6AF8mIgm+Zi0dZ3ACoIg+QtpA==} engines: {node: '>= 4'} recma-build-jsx@1.0.0: @@ -12551,6 +12636,10 @@ packages: resolution: {integrity: sha512-21IYA3Q5cQf089Z6tgaUTr7lDAyzoTPx5HRtbhsME8Udispad8dC/+sziTNugOEx54ilvatQ9YCzl4KQLPcRHA==} engines: {node: '>=11.0.0'} + sax@1.6.0: + resolution: {integrity: sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==} + engines: {node: '>=11.0.0'} + saxes@6.0.0: resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} engines: {node: '>=v12.22.7'} @@ -12627,6 +12716,11 @@ packages: engines: {node: '>=10'} hasBin: true + semver@7.8.5: + resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} + engines: {node: '>=10'} + hasBin: true + send@0.19.0: resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} engines: {node: '>= 0.8.0'} @@ -12748,6 +12842,10 @@ packages: resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} engines: {node: '>= 0.4'} + side-channel-list@1.0.1: + resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==} + engines: {node: '>= 0.4'} + side-channel-map@1.0.1: resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} engines: {node: '>= 0.4'} @@ -12760,6 +12858,10 @@ packages: resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} engines: {node: '>= 0.4'} + side-channel@1.1.1: + resolution: {integrity: sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==} + engines: {node: '>= 0.4'} + sift@17.1.3: resolution: {integrity: sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==} @@ -13108,8 +13210,8 @@ packages: svg-parser@2.0.4: resolution: {integrity: sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==} - svgo@3.3.3: - resolution: {integrity: sha512-+wn7I4p7YgJhHs38k2TNjy1vCfPIfLIJWR5MnCStsN8WuuTcBnRKcMHQLMM2ijxGZmDoZwNv8ipl5aTTen62ng==} + svgo@3.3.4: + resolution: {integrity: sha512-GsNRis4e8jxn2Y9ENz/8lbJ93CstG8svtMnuRaHbiF2LTJ5tK0/q3t/URPq9Zc7zVWBJnNnJMIp6bevK7bSmNg==} engines: {node: '>=14.0.0'} hasBin: true @@ -13145,6 +13247,10 @@ packages: resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} engines: {node: '>=6'} + tapable@2.3.3: + resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} + engines: {node: '>=6'} + tar-stream@3.1.7: resolution: {integrity: sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==} @@ -13168,11 +13274,59 @@ packages: uglify-js: optional: true + terser-webpack-plugin@5.6.1: + resolution: {integrity: sha512-201R5j+sJpK8nFWwKVyNfZot8FaJbLZDq5evriVzbV1wDtSXDjRUDRfJzHpAaxFDMEhsZL1QkeqM61wgsS3KaQ==} + engines: {node: '>= 10.13.0'} + peerDependencies: + '@minify-html/node': '*' + '@swc/core': '*' + '@swc/css': '*' + '@swc/html': '*' + clean-css: '*' + cssnano: '*' + csso: '*' + esbuild: '*' + html-minifier-terser: '*' + lightningcss: '*' + postcss: '*' + uglify-js: '*' + webpack: ^5.105.4 + peerDependenciesMeta: + '@minify-html/node': + optional: true + '@swc/core': + optional: true + '@swc/css': + optional: true + '@swc/html': + optional: true + clean-css: + optional: true + cssnano: + optional: true + csso: + optional: true + esbuild: + optional: true + html-minifier-terser: + optional: true + lightningcss: + optional: true + postcss: + optional: true + uglify-js: + optional: true + terser@5.44.1: resolution: {integrity: sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==} engines: {node: '>=10'} hasBin: true + terser@5.49.0: + resolution: {integrity: sha512-SNiDnXyHSrxVcIOtVbULzcTmniUiwcV7Nwdyj1twVubeTmbjoa8p69KKDpfkdoOavuM4/GRm1+ykI8qqnavHoA==} + engines: {node: '>=10'} + hasBin: true + test-exclude@7.0.2: resolution: {integrity: sha512-u9E6A+ZDYdp7a4WnarkXPZOx8Ilz46+kby6p1yZ8zsGTz9gYa6FIS7lj2oezzNKmtdyyJNNmmXDppga5GB7kSw==} engines: {node: '>=18'} @@ -13245,10 +13399,6 @@ packages: resolution: {integrity: sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==} engines: {node: '>=18'} - tinyglobby@0.2.15: - resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} - engines: {node: '>=12.0.0'} - tinyglobby@0.2.17: resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} engines: {node: '>=12.0.0'} @@ -13484,6 +13634,9 @@ packages: undici-types@7.16.0: resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + undici-types@8.3.0: + resolution: {integrity: sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==} + unicode-canonical-property-names-ecmascript@2.0.1: resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} engines: {node: '>=4'} @@ -13734,20 +13887,20 @@ packages: yaml: optional: true - vitest@4.1.8: - resolution: {integrity: sha512-flY6ScbCIt9HThs+C5HS7jvGOB560DJtk/Z15IQROTA6zEy49Nh8T/dofWTQL+n3vswqn87sbJNiuqw1SDp5Ig==} + vitest@4.1.10: + resolution: {integrity: sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==} engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@opentelemetry/api': ^1.9.0 '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 - '@vitest/browser-playwright': 4.1.8 - '@vitest/browser-preview': 4.1.8 - '@vitest/browser-webdriverio': 4.1.8 - '@vitest/coverage-istanbul': 4.1.8 - '@vitest/coverage-v8': 4.1.8 - '@vitest/ui': 4.1.8 + '@vitest/browser-playwright': 4.1.10 + '@vitest/browser-preview': 4.1.10 + '@vitest/browser-webdriverio': 4.1.10 + '@vitest/coverage-istanbul': 4.1.10 + '@vitest/coverage-v8': 4.1.10 + '@vitest/ui': 4.1.10 happy-dom: 20.10.1 jsdom: '*' vite: 8.0.16 @@ -13789,8 +13942,8 @@ packages: warning@4.0.3: resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==} - watchpack@2.5.1: - resolution: {integrity: sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==} + watchpack@2.5.2: + resolution: {integrity: sha512-6i/00NBjP4yGPs+caKSyRfpTF/8Torsu0MOW3mMzIbhgISFder8i7xbqgHlLMwJrdiN8ndBV3UA1/AfzPSr+jg==} engines: {node: '>=10.13.0'} wbuf@1.7.3: @@ -13848,8 +14001,8 @@ packages: resolution: {integrity: sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==} engines: {node: '>=18.0.0'} - webpack-sources@3.3.4: - resolution: {integrity: sha512-7tP1PdV4vF+lYPnkMR0jMY5/la2ub5Fc/8VQrrU+lXkiM6C4TjVfGw7iKfyhnTQOsD+6Q/iKw0eFciziRgD58Q==} + webpack-sources@3.5.1: + resolution: {integrity: sha512-jyuiGJdtvY434z5bUZrjz67v76/ePNvFZTp9Mdz29IlH4+GPsgyGjiv0fKI+M7BdkU6ADjulUcKAd3tUK3WlEw==} engines: {node: '>=10.13.0'} webpack-virtual-modules@0.6.2: @@ -13877,8 +14030,8 @@ packages: webpack: optional: true - websocket-driver@0.7.4: - resolution: {integrity: sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==} + websocket-driver@0.7.5: + resolution: {integrity: sha512-ZL2+3c7kMBdIRCMz6l8jQMHyGVxj+UL+xVk74Ombiciboca8rHa15L86B19E5oh1pL9Ii/uj54gtsIrZGMo6zA==} engines: {node: '>=0.8.0'} websocket-extensions@0.1.4: @@ -13979,8 +14132,8 @@ packages: write-file-atomic@3.0.3: resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} - ws@8.21.0: - resolution: {integrity: sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==} + ws@8.21.1: + resolution: {integrity: sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -14238,13 +14391,13 @@ snapshots: '@alloc/quick-lru@5.2.0': {} - '@amiceli/vitest-cucumber@6.3.0(vitest@4.1.8)': + '@amiceli/vitest-cucumber@6.3.0(vitest@4.1.10)': dependencies: callsites: 4.2.0 minimist: 1.2.8 parsecurrency: 1.1.1 ts-morph: 27.0.2 - vitest: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) '@ant-design/cli@6.3.5(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': dependencies: @@ -14295,7 +14448,7 @@ snapshots: '@ant-design/fast-color@2.0.6': dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.29.7 '@ant-design/fast-color@3.0.1': {} @@ -14382,7 +14535,7 @@ snapshots: dependencies: graphql: 16.12.0 - '@apollo/client@3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + '@apollo/client@3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: '@graphql-typed-document-node/core': 3.2.0(graphql@16.12.0) '@wry/caches': 1.0.1 @@ -14399,7 +14552,7 @@ snapshots: tslib: 2.8.1 zen-observable-ts: 1.2.5 optionalDependencies: - graphql-ws: 6.0.6(graphql@16.12.0)(ws@8.21.0) + graphql-ws: 6.0.6(graphql@16.12.0)(ws@8.21.1) react: 19.2.0 react-dom: 19.2.0(react@19.2.0) transitivePeerDependencies: @@ -14512,7 +14665,7 @@ snapshots: dependencies: '@babel/generator': 7.29.7 '@babel/parser': 7.29.7 - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.29.7 chalk: 4.1.2 fb-watchman: 2.0.2 graphql: 16.12.0 @@ -14750,7 +14903,7 @@ snapshots: '@azure/ms-rest-js@1.11.2': dependencies: '@azure/core-auth': 1.10.1 - axios: 1.16.0 + axios: 1.18.0(supports-color@8.1.1) form-data: 4.0.6 tough-cookie: 4.1.3 tslib: 1.14.1 @@ -15617,6 +15770,8 @@ snapshots: '@babel/runtime@7.28.4': {} + '@babel/runtime@7.29.7': {} + '@babel/template@7.27.2': dependencies: '@babel/code-frame': 7.29.0 @@ -15626,8 +15781,8 @@ snapshots: '@babel/template@7.28.6': dependencies: '@babel/code-frame': 7.29.0 - '@babel/parser': 7.29.2 - '@babel/types': 7.29.0 + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 '@babel/template@7.29.7': dependencies: @@ -15713,12 +15868,12 @@ snapshots: '@blazediff/core@1.9.1': {} - '@chromatic-com/storybook@5.2.1(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))': + '@chromatic-com/storybook@5.2.1(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))': dependencies: '@neoconfetti/react': 1.0.0 chromatic: 16.10.0 jsonfile: 6.2.0 - storybook: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + storybook: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0) strip-ansi: 7.1.2 transitivePeerDependencies: - '@chromatic-com/cypress' @@ -16236,7 +16391,7 @@ snapshots: transitivePeerDependencies: - '@algolia/client-search' - '@docusaurus/babel@3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + '@docusaurus/babel@3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: '@babel/core': 7.29.6(supports-color@8.1.1) '@babel/generator': 7.29.1 @@ -16248,13 +16403,22 @@ snapshots: '@babel/runtime': 7.28.4 '@babel/traverse': 7.29.0 '@docusaurus/logger': 3.10.1 - '@docusaurus/utils': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) babel-plugin-dynamic-import-node: 2.3.3 fs-extra: 11.3.2 tslib: 2.8.1 transitivePeerDependencies: + - '@minify-html/node' - '@swc/core' + - '@swc/css' + - '@swc/html' + - clean-css + - cssnano + - csso - esbuild + - html-minifier-terser + - lightningcss + - postcss - react - react-dom - supports-color @@ -16264,34 +16428,36 @@ snapshots: '@docusaurus/bundler@3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3)': dependencies: '@babel/core': 7.29.6(supports-color@8.1.1) - '@docusaurus/babel': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/babel': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@docusaurus/cssnano-preset': 3.10.1 '@docusaurus/logger': 3.10.1 - '@docusaurus/types': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/utils': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - babel-loader: 9.2.1(@babel/core@7.29.6)(webpack@5.105.4(esbuild@0.28.1)) + '@docusaurus/types': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + babel-loader: 9.2.1(@babel/core@7.29.6)(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)) clean-css: 5.3.3 - copy-webpack-plugin: 11.0.0(webpack@5.105.4(esbuild@0.28.1)) - css-loader: 6.11.0(webpack@5.105.4(esbuild@0.28.1)) - css-minimizer-webpack-plugin: 5.0.1(clean-css@5.3.3)(esbuild@0.28.1)(webpack@5.105.4(esbuild@0.28.1)) + copy-webpack-plugin: 11.0.0(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)) + css-loader: 6.11.0(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)) + css-minimizer-webpack-plugin: 5.0.1(clean-css@5.3.3)(esbuild@0.28.1)(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)) cssnano: 6.1.2(postcss@8.5.10) - file-loader: 6.2.0(webpack@5.105.4(esbuild@0.28.1)) + file-loader: 6.2.0(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)) html-minifier-terser: 7.2.0 - mini-css-extract-plugin: 2.9.4(webpack@5.105.4(esbuild@0.28.1)) - null-loader: 4.0.1(webpack@5.105.4(esbuild@0.28.1)) + mini-css-extract-plugin: 2.9.4(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)) + null-loader: 4.0.1(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)) postcss: 8.5.10 - postcss-loader: 7.3.4(postcss@8.5.10)(typescript@6.0.3)(webpack@5.105.4(esbuild@0.28.1)) + postcss-loader: 7.3.4(postcss@8.5.10)(typescript@6.0.3)(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)) postcss-preset-env: 10.4.0(postcss@8.5.10) - terser-webpack-plugin: 5.4.0(esbuild@0.28.1)(webpack@5.105.4(esbuild@0.28.1)) + terser-webpack-plugin: 5.4.0(esbuild@0.28.1)(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)) tslib: 2.8.1 - url-loader: 4.1.1(file-loader@6.2.0(webpack@5.105.4(esbuild@0.28.1)))(webpack@5.105.4(esbuild@0.28.1)) - webpack: 5.105.4(esbuild@0.28.1) - webpackbar: 7.0.0(webpack@5.105.4(esbuild@0.28.1)) + url-loader: 4.1.1(file-loader@6.2.0(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)))(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)) + webpack: 5.105.4(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10) + webpackbar: 7.0.0(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)) transitivePeerDependencies: + - '@minify-html/node' - '@parcel/css' - '@rspack/core' - '@swc/core' - '@swc/css' + - '@swc/html' - csso - esbuild - lightningcss @@ -16302,15 +16468,15 @@ snapshots: - uglify-js - webpack-cli - '@docusaurus/core@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3)': + '@docusaurus/core@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3)': dependencies: - '@docusaurus/babel': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/babel': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@docusaurus/bundler': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) '@docusaurus/logger': 3.10.1 - '@docusaurus/mdx-loader': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/utils': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/utils-common': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/utils-validation': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/mdx-loader': 3.10.1(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils-common': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils-validation': 3.10.1(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@mdx-js/react': 3.1.1(@types/react@19.2.7)(react@19.2.0) boxen: 6.2.1 chalk: 4.1.2 @@ -16326,7 +16492,7 @@ snapshots: execa: 5.1.1 fs-extra: 11.3.2 html-tags: 3.3.1 - html-webpack-plugin: 5.6.5(webpack@5.105.4(esbuild@0.28.1)) + html-webpack-plugin: 5.6.5(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)) leven: 3.1.0 lodash: 4.18.1 open: 8.4.2 @@ -16336,7 +16502,7 @@ snapshots: react-dom: 19.2.0(react@19.2.0) react-helmet-async: '@slorber/react-helmet-async@1.3.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0)' react-loadable: '@docusaurus/react-loadable@6.0.0(react@19.2.0)' - react-loadable-ssr-addon-v5-slorber: 1.0.3(@docusaurus/react-loadable@6.0.0(react@19.2.0))(webpack@5.105.4(esbuild@0.28.1)) + react-loadable-ssr-addon-v5-slorber: 1.0.3(@docusaurus/react-loadable@6.0.0(react@19.2.0))(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)) react-router: 5.3.4(react@19.2.0) react-router-config: 5.1.1(react-router@5.3.4(react@19.2.0))(react@19.2.0) react-router-dom: 5.3.4(react@19.2.0) @@ -16345,19 +16511,25 @@ snapshots: tinypool: 1.1.1 tslib: 2.8.1 update-notifier: 6.0.2 - webpack: 5.105.4(esbuild@0.28.1) + webpack: 5.105.4(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10) webpack-bundle-analyzer: 4.10.2 - webpack-dev-server: 5.2.6(webpack@5.105.4(esbuild@0.28.1)) + webpack-dev-server: 5.2.6(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)) webpack-merge: 6.0.1 transitivePeerDependencies: + - '@minify-html/node' - '@parcel/css' - '@rspack/core' - '@swc/core' - '@swc/css' + - '@swc/html' - bufferutil + - clean-css + - cssnano - csso - esbuild + - html-minifier-terser - lightningcss + - postcss - supports-color - typescript - uglify-js @@ -16376,16 +16548,16 @@ snapshots: chalk: 4.1.2 tslib: 2.8.1 - '@docusaurus/mdx-loader@3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + '@docusaurus/mdx-loader@3.10.1(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: '@docusaurus/logger': 3.10.1 - '@docusaurus/utils': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/utils-validation': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils-validation': 3.10.1(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@mdx-js/mdx': 3.1.1 '@slorber/remark-comment': 1.0.0 escape-html: 1.0.3 estree-util-value-to-estree: 3.5.0 - file-loader: 6.2.0(webpack@5.105.4(esbuild@0.28.1)) + file-loader: 6.2.0(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)) fs-extra: 11.3.2 image-size: 2.0.2 mdast-util-mdx: 3.0.0 @@ -16401,19 +16573,28 @@ snapshots: tslib: 2.8.1 unified: 11.0.5 unist-util-visit: 5.0.0 - url-loader: 4.1.1(file-loader@6.2.0(webpack@5.105.4(esbuild@0.28.1)))(webpack@5.105.4(esbuild@0.28.1)) + url-loader: 4.1.1(file-loader@6.2.0(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)))(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)) vfile: 6.0.3 - webpack: 5.105.4(esbuild@0.28.1) + webpack: 5.105.4(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10) transitivePeerDependencies: + - '@minify-html/node' - '@swc/core' + - '@swc/css' + - '@swc/html' + - clean-css + - cssnano + - csso - esbuild + - html-minifier-terser + - lightningcss + - postcss - supports-color - uglify-js - webpack-cli - '@docusaurus/module-type-aliases@3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + '@docusaurus/module-type-aliases@3.10.1(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: - '@docusaurus/types': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/types': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@types/history': 4.7.11 '@types/react': 19.2.7 '@types/react-router-config': 5.0.11 @@ -16423,23 +16604,32 @@ snapshots: react-helmet-async: '@slorber/react-helmet-async@1.3.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0)' react-loadable: '@docusaurus/react-loadable@6.0.0(react@19.2.0)' transitivePeerDependencies: + - '@minify-html/node' - '@swc/core' + - '@swc/css' + - '@swc/html' + - clean-css + - cssnano + - csso - esbuild + - html-minifier-terser + - lightningcss + - postcss - supports-color - uglify-js - webpack-cli - '@docusaurus/plugin-content-blog@3.10.1(@docusaurus/plugin-content-docs@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3))(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3)': + '@docusaurus/plugin-content-blog@3.10.1(@docusaurus/plugin-content-docs@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3))(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3)': dependencies: - '@docusaurus/core': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) + '@docusaurus/core': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) '@docusaurus/logger': 3.10.1 - '@docusaurus/mdx-loader': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/plugin-content-docs': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) - '@docusaurus/theme-common': 3.10.1(@docusaurus/plugin-content-docs@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/types': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/utils': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/utils-common': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/utils-validation': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/mdx-loader': 3.10.1(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/plugin-content-docs': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) + '@docusaurus/theme-common': 3.10.1(@docusaurus/plugin-content-docs@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/types': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils-common': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils-validation': 3.10.1(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) cheerio: 1.0.0-rc.12 combine-promises: 1.2.0 feed: 4.2.2 @@ -16452,35 +16642,41 @@ snapshots: tslib: 2.8.1 unist-util-visit: 5.0.0 utility-types: 3.11.0 - webpack: 5.105.4(esbuild@0.28.1) + webpack: 5.105.4(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10) transitivePeerDependencies: - '@docusaurus/faster' - '@mdx-js/react' + - '@minify-html/node' - '@parcel/css' - '@rspack/core' - '@swc/core' - '@swc/css' + - '@swc/html' - bufferutil + - clean-css + - cssnano - csso - esbuild + - html-minifier-terser - lightningcss + - postcss - supports-color - typescript - uglify-js - utf-8-validate - webpack-cli - '@docusaurus/plugin-content-docs@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3)': + '@docusaurus/plugin-content-docs@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3)': dependencies: - '@docusaurus/core': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) + '@docusaurus/core': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) '@docusaurus/logger': 3.10.1 - '@docusaurus/mdx-loader': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/module-type-aliases': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/theme-common': 3.10.1(@docusaurus/plugin-content-docs@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/types': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/utils': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/utils-common': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/utils-validation': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/mdx-loader': 3.10.1(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/module-type-aliases': 3.10.1(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/theme-common': 3.10.1(@docusaurus/plugin-content-docs@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/types': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils-common': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils-validation': 3.10.1(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@types/react-router-config': 5.0.11 combine-promises: 1.2.0 fs-extra: 11.3.2 @@ -16491,71 +16687,89 @@ snapshots: schema-dts: 1.1.5 tslib: 2.8.1 utility-types: 3.11.0 - webpack: 5.105.4(esbuild@0.28.1) + webpack: 5.105.4(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10) transitivePeerDependencies: - '@docusaurus/faster' - '@mdx-js/react' + - '@minify-html/node' - '@parcel/css' - '@rspack/core' - '@swc/core' - '@swc/css' + - '@swc/html' - bufferutil + - clean-css + - cssnano - csso - esbuild + - html-minifier-terser - lightningcss + - postcss - supports-color - typescript - uglify-js - utf-8-validate - webpack-cli - '@docusaurus/plugin-content-pages@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3)': + '@docusaurus/plugin-content-pages@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3)': dependencies: - '@docusaurus/core': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) - '@docusaurus/mdx-loader': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/types': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/utils': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/utils-validation': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/core': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) + '@docusaurus/mdx-loader': 3.10.1(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/types': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils-validation': 3.10.1(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) fs-extra: 11.3.2 react: 19.2.0 react-dom: 19.2.0(react@19.2.0) tslib: 2.8.1 - webpack: 5.105.4(esbuild@0.28.1) + webpack: 5.105.4(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10) transitivePeerDependencies: - '@docusaurus/faster' - '@mdx-js/react' + - '@minify-html/node' - '@parcel/css' - '@rspack/core' - '@swc/core' - '@swc/css' + - '@swc/html' - bufferutil + - clean-css + - cssnano - csso - esbuild + - html-minifier-terser - lightningcss + - postcss - supports-color - typescript - uglify-js - utf-8-validate - webpack-cli - '@docusaurus/plugin-css-cascade-layers@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3)': + '@docusaurus/plugin-css-cascade-layers@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3)': dependencies: - '@docusaurus/core': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) - '@docusaurus/types': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/utils': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/utils-validation': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/core': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) + '@docusaurus/types': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils-validation': 3.10.1(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) tslib: 2.8.1 transitivePeerDependencies: - '@docusaurus/faster' - '@mdx-js/react' + - '@minify-html/node' - '@parcel/css' - '@rspack/core' - '@swc/core' - '@swc/css' + - '@swc/html' - bufferutil + - clean-css + - cssnano - csso - esbuild + - html-minifier-terser - lightningcss + - postcss - react - react-dom - supports-color @@ -16564,11 +16778,11 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/plugin-debug@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3)': + '@docusaurus/plugin-debug@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3)': dependencies: - '@docusaurus/core': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) - '@docusaurus/types': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/utils': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/core': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) + '@docusaurus/types': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) fs-extra: 11.3.2 react: 19.2.0 react-dom: 19.2.0(react@19.2.0) @@ -16577,50 +16791,62 @@ snapshots: transitivePeerDependencies: - '@docusaurus/faster' - '@mdx-js/react' + - '@minify-html/node' - '@parcel/css' - '@rspack/core' - '@swc/core' - '@swc/css' + - '@swc/html' - bufferutil + - clean-css + - cssnano - csso - esbuild + - html-minifier-terser - lightningcss + - postcss - supports-color - typescript - uglify-js - utf-8-validate - webpack-cli - '@docusaurus/plugin-google-analytics@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3)': + '@docusaurus/plugin-google-analytics@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3)': dependencies: - '@docusaurus/core': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) - '@docusaurus/types': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/utils-validation': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/core': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) + '@docusaurus/types': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils-validation': 3.10.1(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react: 19.2.0 react-dom: 19.2.0(react@19.2.0) tslib: 2.8.1 transitivePeerDependencies: - '@docusaurus/faster' - '@mdx-js/react' + - '@minify-html/node' - '@parcel/css' - '@rspack/core' - '@swc/core' - '@swc/css' + - '@swc/html' - bufferutil + - clean-css + - cssnano - csso - esbuild + - html-minifier-terser - lightningcss + - postcss - supports-color - typescript - uglify-js - utf-8-validate - webpack-cli - '@docusaurus/plugin-google-gtag@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3)': + '@docusaurus/plugin-google-gtag@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3)': dependencies: - '@docusaurus/core': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) - '@docusaurus/types': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/utils-validation': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/core': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) + '@docusaurus/types': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils-validation': 3.10.1(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@types/gtag.js': 0.0.20 react: 19.2.0 react-dom: 19.2.0(react@19.2.0) @@ -16628,53 +16854,65 @@ snapshots: transitivePeerDependencies: - '@docusaurus/faster' - '@mdx-js/react' + - '@minify-html/node' - '@parcel/css' - '@rspack/core' - '@swc/core' - '@swc/css' + - '@swc/html' - bufferutil + - clean-css + - cssnano - csso - esbuild + - html-minifier-terser - lightningcss + - postcss - supports-color - typescript - uglify-js - utf-8-validate - webpack-cli - '@docusaurus/plugin-google-tag-manager@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3)': + '@docusaurus/plugin-google-tag-manager@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3)': dependencies: - '@docusaurus/core': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) - '@docusaurus/types': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/utils-validation': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/core': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) + '@docusaurus/types': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils-validation': 3.10.1(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react: 19.2.0 react-dom: 19.2.0(react@19.2.0) tslib: 2.8.1 transitivePeerDependencies: - '@docusaurus/faster' - '@mdx-js/react' + - '@minify-html/node' - '@parcel/css' - '@rspack/core' - '@swc/core' - '@swc/css' + - '@swc/html' - bufferutil + - clean-css + - cssnano - csso - esbuild + - html-minifier-terser - lightningcss + - postcss - supports-color - typescript - uglify-js - utf-8-validate - webpack-cli - '@docusaurus/plugin-sitemap@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3)': + '@docusaurus/plugin-sitemap@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3)': dependencies: - '@docusaurus/core': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) + '@docusaurus/core': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) '@docusaurus/logger': 3.10.1 - '@docusaurus/types': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/utils': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/utils-common': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/utils-validation': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/types': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils-common': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils-validation': 3.10.1(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) fs-extra: 11.3.2 react: 19.2.0 react-dom: 19.2.0(react@19.2.0) @@ -16683,81 +16921,99 @@ snapshots: transitivePeerDependencies: - '@docusaurus/faster' - '@mdx-js/react' + - '@minify-html/node' - '@parcel/css' - '@rspack/core' - '@swc/core' - '@swc/css' + - '@swc/html' - bufferutil + - clean-css + - cssnano - csso - esbuild + - html-minifier-terser - lightningcss + - postcss - supports-color - typescript - uglify-js - utf-8-validate - webpack-cli - '@docusaurus/plugin-svgr@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3)': + '@docusaurus/plugin-svgr@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3)': dependencies: - '@docusaurus/core': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) - '@docusaurus/types': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/utils': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/utils-validation': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/core': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) + '@docusaurus/types': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils-validation': 3.10.1(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@svgr/core': 8.1.0(typescript@6.0.3) '@svgr/webpack': 8.1.0(typescript@6.0.3) react: 19.2.0 react-dom: 19.2.0(react@19.2.0) tslib: 2.8.1 - webpack: 5.105.4(esbuild@0.28.1) + webpack: 5.105.4(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10) transitivePeerDependencies: - '@docusaurus/faster' - '@mdx-js/react' + - '@minify-html/node' - '@parcel/css' - '@rspack/core' - '@swc/core' - '@swc/css' + - '@swc/html' - bufferutil + - clean-css + - cssnano - csso - esbuild + - html-minifier-terser - lightningcss + - postcss - supports-color - typescript - uglify-js - utf-8-validate - webpack-cli - '@docusaurus/preset-classic@3.10.1(@algolia/client-search@5.45.0)(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(@types/react@19.2.7)(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(search-insights@2.17.3)(typescript@6.0.3)': - dependencies: - '@docusaurus/core': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) - '@docusaurus/plugin-content-blog': 3.10.1(@docusaurus/plugin-content-docs@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3))(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) - '@docusaurus/plugin-content-docs': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) - '@docusaurus/plugin-content-pages': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) - '@docusaurus/plugin-css-cascade-layers': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) - '@docusaurus/plugin-debug': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) - '@docusaurus/plugin-google-analytics': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) - '@docusaurus/plugin-google-gtag': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) - '@docusaurus/plugin-google-tag-manager': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) - '@docusaurus/plugin-sitemap': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) - '@docusaurus/plugin-svgr': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) + '@docusaurus/preset-classic@3.10.1(@algolia/client-search@5.45.0)(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(@types/react@19.2.7)(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(search-insights@2.17.3)(typescript@6.0.3)': + dependencies: + '@docusaurus/core': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) + '@docusaurus/plugin-content-blog': 3.10.1(@docusaurus/plugin-content-docs@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3))(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) + '@docusaurus/plugin-content-docs': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) + '@docusaurus/plugin-content-pages': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) + '@docusaurus/plugin-css-cascade-layers': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) + '@docusaurus/plugin-debug': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) + '@docusaurus/plugin-google-analytics': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) + '@docusaurus/plugin-google-gtag': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) + '@docusaurus/plugin-google-tag-manager': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) + '@docusaurus/plugin-sitemap': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) + '@docusaurus/plugin-svgr': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) '@docusaurus/theme-classic': 3.10.1(@types/react@19.2.7)(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) - '@docusaurus/theme-common': 3.10.1(@docusaurus/plugin-content-docs@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/theme-search-algolia': 3.10.1(@algolia/client-search@5.45.0)(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(@types/react@19.2.7)(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(search-insights@2.17.3)(typescript@6.0.3) - '@docusaurus/types': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/theme-common': 3.10.1(@docusaurus/plugin-content-docs@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/theme-search-algolia': 3.10.1(@algolia/client-search@5.45.0)(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(@types/react@19.2.7)(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(search-insights@2.17.3)(typescript@6.0.3) + '@docusaurus/types': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react: 19.2.0 react-dom: 19.2.0(react@19.2.0) transitivePeerDependencies: - '@algolia/client-search' - '@docusaurus/faster' - '@mdx-js/react' + - '@minify-html/node' - '@parcel/css' - '@rspack/core' - '@swc/core' - '@swc/css' + - '@swc/html' - '@types/react' - bufferutil + - clean-css + - cssnano - csso - esbuild + - html-minifier-terser - lightningcss + - postcss - search-insights - supports-color - typescript @@ -16772,19 +17028,19 @@ snapshots: '@docusaurus/theme-classic@3.10.1(@types/react@19.2.7)(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3)': dependencies: - '@docusaurus/core': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) + '@docusaurus/core': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) '@docusaurus/logger': 3.10.1 - '@docusaurus/mdx-loader': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/module-type-aliases': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/plugin-content-blog': 3.10.1(@docusaurus/plugin-content-docs@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3))(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) - '@docusaurus/plugin-content-docs': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) - '@docusaurus/plugin-content-pages': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) - '@docusaurus/theme-common': 3.10.1(@docusaurus/plugin-content-docs@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/mdx-loader': 3.10.1(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/module-type-aliases': 3.10.1(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/plugin-content-blog': 3.10.1(@docusaurus/plugin-content-docs@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3))(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) + '@docusaurus/plugin-content-docs': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) + '@docusaurus/plugin-content-pages': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) + '@docusaurus/theme-common': 3.10.1(@docusaurus/plugin-content-docs@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@docusaurus/theme-translations': 3.10.1 - '@docusaurus/types': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/utils': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/utils-common': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/utils-validation': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/types': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils-common': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils-validation': 3.10.1(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@mdx-js/react': 3.1.1(@types/react@19.2.7)(react@19.2.0) clsx: 2.1.1 copy-text-to-clipboard: 3.2.2 @@ -16802,14 +17058,19 @@ snapshots: utility-types: 3.11.0 transitivePeerDependencies: - '@docusaurus/faster' + - '@minify-html/node' - '@parcel/css' - '@rspack/core' - '@swc/core' - '@swc/css' + - '@swc/html' - '@types/react' - bufferutil + - clean-css + - cssnano - csso - esbuild + - html-minifier-terser - lightningcss - supports-color - typescript @@ -16817,13 +17078,13 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/theme-common@3.10.1(@docusaurus/plugin-content-docs@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + '@docusaurus/theme-common@3.10.1(@docusaurus/plugin-content-docs@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: - '@docusaurus/mdx-loader': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/module-type-aliases': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/plugin-content-docs': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) - '@docusaurus/utils': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/utils-common': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/mdx-loader': 3.10.1(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/module-type-aliases': 3.10.1(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/plugin-content-docs': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) + '@docusaurus/utils': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils-common': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@types/history': 4.7.11 '@types/react': 19.2.7 '@types/react-router-config': 5.0.11 @@ -16835,23 +17096,32 @@ snapshots: tslib: 2.8.1 utility-types: 3.11.0 transitivePeerDependencies: + - '@minify-html/node' - '@swc/core' + - '@swc/css' + - '@swc/html' + - clean-css + - cssnano + - csso - esbuild + - html-minifier-terser + - lightningcss + - postcss - supports-color - uglify-js - webpack-cli - '@docusaurus/theme-search-algolia@3.10.1(@algolia/client-search@5.45.0)(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(@types/react@19.2.7)(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(search-insights@2.17.3)(typescript@6.0.3)': + '@docusaurus/theme-search-algolia@3.10.1(@algolia/client-search@5.45.0)(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(@types/react@19.2.7)(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(search-insights@2.17.3)(typescript@6.0.3)': dependencies: '@algolia/autocomplete-core': 1.19.2(@algolia/client-search@5.45.0)(algoliasearch@5.45.0)(search-insights@2.17.3) '@docsearch/react': 4.3.2(@algolia/client-search@5.45.0)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(search-insights@2.17.3) - '@docusaurus/core': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) + '@docusaurus/core': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) '@docusaurus/logger': 3.10.1 - '@docusaurus/plugin-content-docs': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) - '@docusaurus/theme-common': 3.10.1(@docusaurus/plugin-content-docs@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3))(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/plugin-content-docs': 3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3) + '@docusaurus/theme-common': 3.10.1(@docusaurus/plugin-content-docs@3.10.1(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.0))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(typescript@6.0.3))(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@docusaurus/theme-translations': 3.10.1 - '@docusaurus/utils': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/utils-validation': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils-validation': 3.10.1(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) algoliasearch: 5.45.0 algoliasearch-helper: 3.26.1(algoliasearch@5.45.0) clsx: 2.1.1 @@ -16866,15 +17136,21 @@ snapshots: - '@algolia/client-search' - '@docusaurus/faster' - '@mdx-js/react' + - '@minify-html/node' - '@parcel/css' - '@rspack/core' - '@swc/core' - '@swc/css' + - '@swc/html' - '@types/react' - bufferutil + - clean-css + - cssnano - csso - esbuild + - html-minifier-terser - lightningcss + - postcss - search-insights - supports-color - typescript @@ -16889,7 +17165,7 @@ snapshots: '@docusaurus/tsconfig@3.10.1': {} - '@docusaurus/types@3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + '@docusaurus/types@3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: '@mdx-js/mdx': 3.1.1 '@types/history': 4.7.11 @@ -16901,55 +17177,82 @@ snapshots: react-dom: 19.2.0(react@19.2.0) react-helmet-async: '@slorber/react-helmet-async@1.3.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0)' utility-types: 3.11.0 - webpack: 5.105.4(esbuild@0.28.1) + webpack: 5.105.4(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10) webpack-merge: 5.10.0 transitivePeerDependencies: + - '@minify-html/node' - '@swc/core' + - '@swc/css' + - '@swc/html' + - clean-css + - cssnano + - csso - esbuild + - html-minifier-terser + - lightningcss + - postcss - supports-color - uglify-js - webpack-cli - '@docusaurus/utils-common@3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + '@docusaurus/utils-common@3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: - '@docusaurus/types': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/types': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) tslib: 2.8.1 transitivePeerDependencies: + - '@minify-html/node' - '@swc/core' + - '@swc/css' + - '@swc/html' + - clean-css + - cssnano + - csso - esbuild + - html-minifier-terser + - lightningcss + - postcss - react - react-dom - supports-color - uglify-js - webpack-cli - '@docusaurus/utils-validation@3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + '@docusaurus/utils-validation@3.10.1(esbuild@0.28.1)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: '@docusaurus/logger': 3.10.1 - '@docusaurus/utils': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/utils-common': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils-common': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) fs-extra: 11.3.2 joi: 17.13.4 js-yaml: 4.3.0 lodash: 4.18.1 tslib: 2.8.1 transitivePeerDependencies: + - '@minify-html/node' - '@swc/core' + - '@swc/css' + - '@swc/html' + - clean-css + - cssnano + - csso - esbuild + - html-minifier-terser + - lightningcss + - postcss - react - react-dom - supports-color - uglify-js - webpack-cli - '@docusaurus/utils@3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + '@docusaurus/utils@3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: '@docusaurus/logger': 3.10.1 - '@docusaurus/types': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@docusaurus/utils-common': 3.10.1(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/types': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@docusaurus/utils-common': 3.10.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) escape-string-regexp: 4.0.0 execa: 5.1.1 - file-loader: 6.2.0(webpack@5.105.4(esbuild@0.28.1)) + file-loader: 6.2.0(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)) fs-extra: 11.3.2 github-slugger: 1.5.0 globby: 11.1.0 @@ -16962,12 +17265,21 @@ snapshots: prompts: 2.4.2 resolve-pathname: 3.0.0 tslib: 2.8.1 - url-loader: 4.1.1(file-loader@6.2.0(webpack@5.105.4(esbuild@0.28.1)))(webpack@5.105.4(esbuild@0.28.1)) + url-loader: 4.1.1(file-loader@6.2.0(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)))(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)) utility-types: 3.11.0 - webpack: 5.105.4(esbuild@0.28.1) + webpack: 5.105.4(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10) transitivePeerDependencies: + - '@minify-html/node' - '@swc/core' + - '@swc/css' + - '@swc/html' + - clean-css + - cssnano + - csso - esbuild + - html-minifier-terser + - lightningcss + - postcss - react - react-dom - supports-color @@ -16985,6 +17297,12 @@ snapshots: tslib: 2.8.1 optional: true + '@emnapi/core@1.11.2': + dependencies: + '@emnapi/wasi-threads': 1.2.2 + tslib: 2.8.1 + optional: true + '@emnapi/core@1.9.2': dependencies: '@emnapi/wasi-threads': 1.2.1 @@ -16996,6 +17314,11 @@ snapshots: tslib: 2.8.1 optional: true + '@emnapi/runtime@1.11.2': + dependencies: + tslib: 2.8.1 + optional: true + '@emnapi/runtime@1.9.2': dependencies: tslib: 2.8.1 @@ -17006,6 +17329,11 @@ snapshots: tslib: 2.8.1 optional: true + '@emnapi/wasi-threads@1.2.2': + dependencies: + tslib: 2.8.1 + optional: true + '@emotion/hash@0.8.0': {} '@emotion/unitless@0.7.5': {} @@ -17376,10 +17704,10 @@ snapshots: '@graphql-tools/utils': 10.11.0(graphql@16.12.0) '@whatwg-node/disposablestack': 0.0.6 graphql: 16.12.0 - graphql-ws: 6.0.6(graphql@16.12.0)(ws@8.21.0) - isomorphic-ws: 5.0.0(ws@8.21.0) + graphql-ws: 6.0.6(graphql@16.12.0)(ws@8.21.1) + isomorphic-ws: 5.0.0(ws@8.21.1) tslib: 2.8.1 - ws: 8.21.0 + ws: 8.21.1 transitivePeerDependencies: - '@fastify/websocket' - bufferutil @@ -17407,9 +17735,9 @@ snapshots: '@graphql-tools/utils': 10.11.0(graphql@16.12.0) '@types/ws': 8.18.1 graphql: 16.12.0 - isomorphic-ws: 5.0.0(ws@8.21.0) + isomorphic-ws: 5.0.0(ws@8.21.1) tslib: 2.8.1 - ws: 8.21.0 + ws: 8.21.1 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -17464,10 +17792,10 @@ snapshots: '@graphql-tools/graphql-tag-pluck@8.3.26(graphql@16.12.0)': dependencies: '@babel/core': 7.29.6(supports-color@8.1.1) - '@babel/parser': 7.29.2 + '@babel/parser': 7.29.7 '@babel/plugin-syntax-import-assertions': 7.27.1(@babel/core@7.29.6) '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 + '@babel/types': 7.29.7 '@graphql-tools/utils': 10.11.0(graphql@16.12.0) graphql: 16.12.0 tslib: 2.8.1 @@ -17581,10 +17909,10 @@ snapshots: '@whatwg-node/fetch': 0.10.13 '@whatwg-node/promise-helpers': 1.3.2 graphql: 16.12.0 - isomorphic-ws: 5.0.0(ws@8.21.0) + isomorphic-ws: 5.0.0(ws@8.21.1) sync-fetch: 0.6.0-2 tslib: 2.8.1 - ws: 8.21.0 + ws: 8.21.1 transitivePeerDependencies: - '@fastify/websocket' - '@types/node' @@ -17676,11 +18004,19 @@ snapshots: '@types/yargs': 17.0.35 chalk: 4.1.2 - '@joshwooding/vite-plugin-react-docgen-typescript@0.7.0(typescript@6.0.3)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': + '@joshwooding/vite-plugin-react-docgen-typescript@0.7.0(typescript@6.0.3)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))': + dependencies: + glob: 13.0.6 + react-docgen-typescript: 2.4.0(typescript@6.0.3) + vite: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) + optionalDependencies: + typescript: 6.0.3 + + '@joshwooding/vite-plugin-react-docgen-typescript@0.7.0(typescript@6.0.3)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))': dependencies: glob: 13.0.6 react-docgen-typescript: 2.4.0(typescript@6.0.3) - vite: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) optionalDependencies: typescript: 6.0.3 @@ -17801,18 +18137,32 @@ snapshots: '@tybys/wasm-util': 0.10.1 optional: true - '@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': + '@napi-rs/wasm-runtime@1.1.2(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)': + dependencies: + '@emnapi/core': 1.11.2 + '@emnapi/runtime': 1.11.2 + '@tybys/wasm-util': 0.10.1 + optional: true + + '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': dependencies: '@emnapi/core': 1.10.0 '@emnapi/runtime': 1.10.0 - '@tybys/wasm-util': 0.10.1 + '@tybys/wasm-util': 0.10.3 + optional: true + + '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)': + dependencies: + '@emnapi/core': 1.11.2 + '@emnapi/runtime': 1.11.2 + '@tybys/wasm-util': 0.10.3 optional: true - '@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)': + '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)': dependencies: '@emnapi/core': 1.9.2 '@emnapi/runtime': 1.9.2 - '@tybys/wasm-util': 0.10.1 + '@tybys/wasm-util': 0.10.3 optional: true '@neoconfetti/react@1.0.0': {} @@ -17873,6 +18223,11 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/semantic-conventions': 1.38.0 + '@opentelemetry/core@2.9.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/semantic-conventions': 1.38.0 + '@opentelemetry/exporter-logs-otlp-grpc@0.57.2(@opentelemetry/api@1.9.0)': dependencies: '@grpc/grpc-js': 1.14.4 @@ -18077,10 +18432,10 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) - '@opentelemetry/propagator-jaeger@1.30.1(@opentelemetry/api@1.9.0)': + '@opentelemetry/propagator-jaeger@2.9.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.9.0(@opentelemetry/api@1.9.0) '@opentelemetry/resources@1.30.1(@opentelemetry/api@1.9.0)': dependencies: @@ -18165,7 +18520,7 @@ snapshots: '@opentelemetry/context-async-hooks': 1.30.1(@opentelemetry/api@1.9.0) '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) '@opentelemetry/propagator-b3': 1.30.1(@opentelemetry/api@1.9.0) - '@opentelemetry/propagator-jaeger': 1.30.1(@opentelemetry/api@1.9.0) + '@opentelemetry/propagator-jaeger': 2.9.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-base': 1.30.1(@opentelemetry/api@1.9.0) semver: 7.7.4 @@ -18289,7 +18644,7 @@ snapshots: dependencies: '@emnapi/core': 1.9.2 '@emnapi/runtime': 1.9.2 - '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) + '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) optional: true '@oxc-parser/binding-win32-arm64-msvc@0.121.0': @@ -18321,94 +18676,94 @@ snapshots: '@oxc-resolver/binding-android-arm-eabi@11.14.0': optional: true - '@oxc-resolver/binding-android-arm-eabi@11.20.0': + '@oxc-resolver/binding-android-arm-eabi@11.24.2': optional: true '@oxc-resolver/binding-android-arm64@11.14.0': optional: true - '@oxc-resolver/binding-android-arm64@11.20.0': + '@oxc-resolver/binding-android-arm64@11.24.2': optional: true '@oxc-resolver/binding-darwin-arm64@11.14.0': optional: true - '@oxc-resolver/binding-darwin-arm64@11.20.0': + '@oxc-resolver/binding-darwin-arm64@11.24.2': optional: true '@oxc-resolver/binding-darwin-x64@11.14.0': optional: true - '@oxc-resolver/binding-darwin-x64@11.20.0': + '@oxc-resolver/binding-darwin-x64@11.24.2': optional: true '@oxc-resolver/binding-freebsd-x64@11.14.0': optional: true - '@oxc-resolver/binding-freebsd-x64@11.20.0': + '@oxc-resolver/binding-freebsd-x64@11.24.2': optional: true '@oxc-resolver/binding-linux-arm-gnueabihf@11.14.0': optional: true - '@oxc-resolver/binding-linux-arm-gnueabihf@11.20.0': + '@oxc-resolver/binding-linux-arm-gnueabihf@11.24.2': optional: true '@oxc-resolver/binding-linux-arm-musleabihf@11.14.0': optional: true - '@oxc-resolver/binding-linux-arm-musleabihf@11.20.0': + '@oxc-resolver/binding-linux-arm-musleabihf@11.24.2': optional: true '@oxc-resolver/binding-linux-arm64-gnu@11.14.0': optional: true - '@oxc-resolver/binding-linux-arm64-gnu@11.20.0': + '@oxc-resolver/binding-linux-arm64-gnu@11.24.2': optional: true '@oxc-resolver/binding-linux-arm64-musl@11.14.0': optional: true - '@oxc-resolver/binding-linux-arm64-musl@11.20.0': + '@oxc-resolver/binding-linux-arm64-musl@11.24.2': optional: true '@oxc-resolver/binding-linux-ppc64-gnu@11.14.0': optional: true - '@oxc-resolver/binding-linux-ppc64-gnu@11.20.0': + '@oxc-resolver/binding-linux-ppc64-gnu@11.24.2': optional: true '@oxc-resolver/binding-linux-riscv64-gnu@11.14.0': optional: true - '@oxc-resolver/binding-linux-riscv64-gnu@11.20.0': + '@oxc-resolver/binding-linux-riscv64-gnu@11.24.2': optional: true '@oxc-resolver/binding-linux-riscv64-musl@11.14.0': optional: true - '@oxc-resolver/binding-linux-riscv64-musl@11.20.0': + '@oxc-resolver/binding-linux-riscv64-musl@11.24.2': optional: true '@oxc-resolver/binding-linux-s390x-gnu@11.14.0': optional: true - '@oxc-resolver/binding-linux-s390x-gnu@11.20.0': + '@oxc-resolver/binding-linux-s390x-gnu@11.24.2': optional: true '@oxc-resolver/binding-linux-x64-gnu@11.14.0': optional: true - '@oxc-resolver/binding-linux-x64-gnu@11.20.0': + '@oxc-resolver/binding-linux-x64-gnu@11.24.2': optional: true '@oxc-resolver/binding-linux-x64-musl@11.14.0': optional: true - '@oxc-resolver/binding-linux-x64-musl@11.20.0': + '@oxc-resolver/binding-linux-x64-musl@11.24.2': optional: true - '@oxc-resolver/binding-openharmony-arm64@11.20.0': + '@oxc-resolver/binding-openharmony-arm64@11.24.2': optional: true '@oxc-resolver/binding-wasm32-wasi@11.14.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': @@ -18419,17 +18774,17 @@ snapshots: - '@emnapi/runtime' optional: true - '@oxc-resolver/binding-wasm32-wasi@11.20.0': + '@oxc-resolver/binding-wasm32-wasi@11.24.2': dependencies: - '@emnapi/core': 1.10.0 - '@emnapi/runtime': 1.10.0 - '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + '@emnapi/core': 1.11.2 + '@emnapi/runtime': 1.11.2 + '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) optional: true '@oxc-resolver/binding-win32-arm64-msvc@11.14.0': optional: true - '@oxc-resolver/binding-win32-arm64-msvc@11.20.0': + '@oxc-resolver/binding-win32-arm64-msvc@11.24.2': optional: true '@oxc-resolver/binding-win32-ia32-msvc@11.14.0': @@ -18438,7 +18793,7 @@ snapshots: '@oxc-resolver/binding-win32-x64-msvc@11.14.0': optional: true - '@oxc-resolver/binding-win32-x64-msvc@11.20.0': + '@oxc-resolver/binding-win32-x64-msvc@11.24.2': optional: true '@paralleldrive/cuid2@2.3.1': @@ -19073,11 +19428,19 @@ snapshots: - '@emnapi/runtime' optional: true + '@rolldown/binding-wasm32-wasi@1.0.0-beta.55(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)': + dependencies: + '@napi-rs/wasm-runtime': 1.1.2(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' + optional: true + '@rolldown/binding-wasm32-wasi@1.0.3': dependencies: '@emnapi/core': 1.10.0 '@emnapi/runtime': 1.10.0 - '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) optional: true '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.55': @@ -19183,7 +19546,7 @@ snapshots: dependencies: '@serenity-js/core': 3.43.0 agent-base: 7.1.4 - axios: 1.16.0 + axios: 1.18.0(supports-color@8.1.1) http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 lru-cache: 11.3.6 @@ -19198,7 +19561,7 @@ snapshots: '@serenity-js/core': 3.43.0 '@serenity-js/rest': 3.43.0 ansi-regex: 5.0.1 - axios: 1.16.0 + axios: 1.18.0(supports-color@8.1.1) chalk: 4.1.2 find-java-home: 2.0.0 progress: 2.0.3 @@ -19229,7 +19592,7 @@ snapshots: '@slorber/react-helmet-async@1.3.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.29.7 invariant: 2.2.4 prop-types: 15.8.1 react: 19.2.0 @@ -19248,10 +19611,10 @@ snapshots: color: 5.0.3 text-hex: 1.0.0 - '@sonar/scan@4.3.2': + '@sonar/scan@4.3.2(supports-color@8.1.1)': dependencies: adm-zip: 0.5.16 - axios: 1.16.0 + axios: 1.18.0(supports-color@8.1.1) commander: 13.1.0 fs-extra: 11.3.2 hpagent: 1.2.0 @@ -19265,24 +19628,63 @@ snapshots: - bare-abort-controller - debug - react-native-b4a + - supports-color '@standard-schema/spec@1.1.0': {} - '@storybook/addon-a11y@10.4.2(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))': + '@storybook/addon-a11y@10.4.2(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))': dependencies: '@storybook/global': 5.0.0 axe-core: 4.11.0 - storybook: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + storybook: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0) + + '@storybook/addon-docs@10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10))': + dependencies: + '@mdx-js/react': 3.1.1(@types/react@19.2.7)(react@19.2.0) + '@storybook/csf-plugin': 10.4.2(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)) + '@storybook/icons': 2.0.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@storybook/react-dom-shim': 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0)) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + storybook: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0) + ts-dedent: 2.2.0 + optionalDependencies: + '@types/react': 19.2.7 + transitivePeerDependencies: + - '@types/react-dom' + - esbuild + - rollup + - vite + - webpack + + '@storybook/addon-docs@10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1))': + dependencies: + '@mdx-js/react': 3.1.1(@types/react@19.2.7)(react@19.2.0) + '@storybook/csf-plugin': 10.4.2(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) + '@storybook/icons': 2.0.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@storybook/react-dom-shim': 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0)) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + storybook: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0) + ts-dedent: 2.2.0 + optionalDependencies: + '@types/react': 19.2.7 + transitivePeerDependencies: + - '@types/react-dom' + - esbuild + - rollup + - vite + - webpack - '@storybook/addon-docs@10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1))': + '@storybook/addon-docs@10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1))': dependencies: '@mdx-js/react': 3.1.1(@types/react@19.2.7)(react@19.2.0) - '@storybook/csf-plugin': 10.4.2(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) + '@storybook/csf-plugin': 10.4.2(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) '@storybook/icons': 2.0.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@storybook/react-dom-shim': 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)) + '@storybook/react-dom-shim': 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0)) react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - storybook: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + storybook: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0) ts-dedent: 2.2.0 optionalDependencies: '@types/react': 19.2.7 @@ -19293,42 +19695,96 @@ snapshots: - vite - webpack - '@storybook/addon-onboarding@10.4.2(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))': + '@storybook/addon-onboarding@10.4.2(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))': + dependencies: + storybook: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0) + + '@storybook/addon-vitest@10.4.2(@vitest/browser-playwright@4.1.10)(@vitest/browser@4.1.10(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.10))(@vitest/runner@4.1.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vitest@4.1.10)': dependencies: - storybook: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@storybook/global': 5.0.0 + '@storybook/icons': 2.0.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + storybook: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0) + optionalDependencies: + '@vitest/browser': 4.1.10(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.10) + '@vitest/browser-playwright': 4.1.10(playwright@1.59.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.10) + '@vitest/runner': 4.1.10 + vitest: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) + transitivePeerDependencies: + - react + - react-dom - '@storybook/addon-vitest@10.4.2(@vitest/browser-playwright@4.1.8)(@vitest/browser@4.1.8(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.8))(@vitest/runner@4.1.8)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(vitest@4.1.8)': + '@storybook/addon-vitest@10.4.2(@vitest/browser-playwright@4.1.10)(@vitest/browser@4.1.10(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.10))(@vitest/runner@4.1.10)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vitest@4.1.10)': dependencies: '@storybook/global': 5.0.0 '@storybook/icons': 2.0.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - storybook: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + storybook: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0) optionalDependencies: - '@vitest/browser': 4.1.8(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.8) - '@vitest/browser-playwright': 4.1.8(playwright@1.59.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.8) - '@vitest/runner': 4.1.8 - vitest: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/browser': 4.1.10(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.10) + '@vitest/browser-playwright': 4.1.10(playwright@1.59.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.10) + '@vitest/runner': 4.1.10 + vitest: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) transitivePeerDependencies: - react - react-dom - '@storybook/builder-vite@10.4.2(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1))': + '@storybook/builder-vite@10.4.2(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10))': + dependencies: + '@storybook/csf-plugin': 10.4.2(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)) + storybook: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0) + ts-dedent: 2.2.0 + vite: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) + transitivePeerDependencies: + - esbuild + - rollup + - webpack + + '@storybook/builder-vite@10.4.2(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1))': dependencies: - '@storybook/csf-plugin': 10.4.2(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) - storybook: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@storybook/csf-plugin': 10.4.2(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) + storybook: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0) ts-dedent: 2.2.0 - vite: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) transitivePeerDependencies: - esbuild - rollup - webpack - '@storybook/csf-plugin@10.4.2(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1))': + '@storybook/builder-vite@10.4.2(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1))': dependencies: - storybook: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@storybook/csf-plugin': 10.4.2(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) + storybook: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0) + ts-dedent: 2.2.0 + vite: 8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) + transitivePeerDependencies: + - esbuild + - rollup + - webpack + + '@storybook/csf-plugin@10.4.2(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10))': + dependencies: + storybook: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0) + unplugin: 2.3.11 + optionalDependencies: + esbuild: 0.28.1 + vite: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) + webpack: 5.105.4(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10) + + '@storybook/csf-plugin@10.4.2(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1))': + dependencies: + storybook: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0) + unplugin: 2.3.11 + optionalDependencies: + esbuild: 0.28.1 + vite: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) + webpack: 5.105.4(esbuild@0.28.1) + + '@storybook/csf-plugin@10.4.2(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1))': + dependencies: + storybook: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0) unplugin: 2.3.11 optionalDependencies: esbuild: 0.28.1 - vite: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) webpack: 5.105.4(esbuild@0.28.1) '@storybook/global@5.0.0': {} @@ -19338,30 +19794,34 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@storybook/react-dom-shim@10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))': + '@storybook/icons@2.1.0(react@19.2.0)': + dependencies: + react: 19.2.0 + + '@storybook/react-dom-shim@10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))': dependencies: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - storybook: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + storybook: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0) optionalDependencies: '@types/react': 19.2.7 '@types/react-dom': 19.2.3(@types/react@19.2.7) - '@storybook/react-vite@10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(typescript@6.0.3)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1))': + '@storybook/react-vite@10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(typescript@6.0.3)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10))': dependencies: - '@joshwooding/vite-plugin-react-docgen-typescript': 0.7.0(typescript@6.0.3)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + '@joshwooding/vite-plugin-react-docgen-typescript': 0.7.0(typescript@6.0.3)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) '@rollup/pluginutils': 5.3.0 - '@storybook/builder-vite': 10.4.2(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) - '@storybook/react': 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(typescript@6.0.3) + '@storybook/builder-vite': 10.4.2(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)) + '@storybook/react': 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(typescript@6.0.3) empathic: 2.0.1 magic-string: 0.30.21 react: 19.2.0 react-docgen: 8.0.2 react-dom: 19.2.0(react@19.2.0) resolve: 1.22.11 - storybook: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + storybook: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0) tsconfig-paths: 4.2.0 - vite: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) transitivePeerDependencies: - '@types/react' - '@types/react-dom' @@ -19371,19 +19831,67 @@ snapshots: - typescript - webpack - '@storybook/react@10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(typescript@6.0.3)': + '@storybook/react-vite@10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(typescript@6.0.3)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1))': dependencies: - '@storybook/global': 5.0.0 - '@storybook/react-dom-shim': 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)) + '@joshwooding/vite-plugin-react-docgen-typescript': 0.7.0(typescript@6.0.3)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) + '@rollup/pluginutils': 5.3.0 + '@storybook/builder-vite': 10.4.2(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) + '@storybook/react': 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(typescript@6.0.3) + empathic: 2.0.1 + magic-string: 0.30.21 react: 19.2.0 react-docgen: 8.0.2 - react-docgen-typescript: 2.4.0(typescript@6.0.3) react-dom: 19.2.0(react@19.2.0) - storybook: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - optionalDependencies: - '@types/react': 19.2.7 - '@types/react-dom': 19.2.3(@types/react@19.2.7) - typescript: 6.0.3 + resolve: 1.22.11 + storybook: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0) + tsconfig-paths: 4.2.0 + vite: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) + transitivePeerDependencies: + - '@types/react' + - '@types/react-dom' + - esbuild + - rollup + - supports-color + - typescript + - webpack + + '@storybook/react-vite@10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(esbuild@0.28.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(typescript@6.0.3)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1))': + dependencies: + '@joshwooding/vite-plugin-react-docgen-typescript': 0.7.0(typescript@6.0.3)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) + '@rollup/pluginutils': 5.3.0 + '@storybook/builder-vite': 10.4.2(esbuild@0.28.1)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(webpack@5.105.4(esbuild@0.28.1)) + '@storybook/react': 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(typescript@6.0.3) + empathic: 2.0.1 + magic-string: 0.30.21 + react: 19.2.0 + react-docgen: 8.0.2 + react-dom: 19.2.0(react@19.2.0) + resolve: 1.22.11 + storybook: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0) + tsconfig-paths: 4.2.0 + vite: 8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) + transitivePeerDependencies: + - '@types/react' + - '@types/react-dom' + - esbuild + - rollup + - supports-color + - typescript + - webpack + + '@storybook/react@10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0))(typescript@6.0.3)': + dependencies: + '@storybook/global': 5.0.0 + '@storybook/react-dom-shim': 10.4.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0)) + react: 19.2.0 + react-docgen: 8.0.2 + react-docgen-typescript: 2.4.0(typescript@6.0.3) + react-dom: 19.2.0(react@19.2.0) + storybook: 10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0) + optionalDependencies: + '@types/react': 19.2.7 + '@types/react-dom': 19.2.3(@types/react@19.2.7) + typescript: 6.0.3 transitivePeerDependencies: - supports-color @@ -19462,7 +19970,7 @@ snapshots: '@svgr/core': 8.1.0(typescript@6.0.3) cosmiconfig: 8.3.6(typescript@6.0.3) deepmerge: 4.3.1 - svgo: 3.3.3 + svgo: 3.3.4 transitivePeerDependencies: - typescript @@ -19489,7 +19997,7 @@ snapshots: '@testing-library/dom@10.4.1': dependencies: '@babel/code-frame': 7.29.7 - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.29.7 '@types/aria-query': 5.0.4 aria-query: 5.3.0 dom-accessibility-api: 0.5.16 @@ -19559,6 +20067,11 @@ snapshots: tslib: 2.8.1 optional: true + '@tybys/wasm-util@0.10.3': + dependencies: + tslib: 2.8.1 + optional: true + '@types/aria-query@5.0.4': {} '@types/babel__core@7.20.5': @@ -19616,11 +20129,11 @@ snapshots: '@types/eslint-scope@3.7.7': dependencies: '@types/eslint': 9.6.1 - '@types/estree': 1.0.8 + '@types/estree': 1.0.9 '@types/eslint@9.6.1': dependencies: - '@types/estree': 1.0.8 + '@types/estree': 1.0.9 '@types/json-schema': 7.0.15 '@types/estree-jsx@1.0.5': @@ -19629,6 +20142,8 @@ snapshots: '@types/estree@1.0.8': {} + '@types/estree@1.0.9': {} + '@types/express-serve-static-core@4.19.7': dependencies: '@types/node': 24.10.1 @@ -19714,6 +20229,10 @@ snapshots: dependencies: undici-types: 7.16.0 + '@types/node@26.1.1': + dependencies: + undici-types: 8.3.0 + '@types/normalize-package-data@2.4.4': {} '@types/prismjs@1.26.5': {} @@ -19806,7 +20325,7 @@ snapshots: '@types/ws@8.18.1': dependencies: - '@types/node': 24.10.1 + '@types/node': 26.1.1 '@types/yargs-parser@21.0.3': {} @@ -19863,18 +20382,37 @@ snapshots: '@vercel/oidc@3.0.5': {} - '@vitejs/plugin-react@6.0.1(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': + '@vitejs/plugin-react@6.0.1(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@rolldown/pluginutils': 1.0.0-rc.7 - vite: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) + + '@vitejs/plugin-react@6.0.1(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))': + dependencies: + '@rolldown/pluginutils': 1.0.0-rc.7 + vite: 8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) + + '@vitest/browser-playwright@4.1.10(playwright@1.59.0)(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.10)': + dependencies: + '@vitest/browser': 4.1.10(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.10) + '@vitest/mocker': 4.1.10(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) + playwright: 1.59.0 + tinyrainbow: 3.1.0 + vitest: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) + transitivePeerDependencies: + - bufferutil + - msw + - utf-8-validate + - vite + optional: true - '@vitest/browser-playwright@4.1.8(playwright@1.59.0)(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.8)': + '@vitest/browser-playwright@4.1.10(playwright@1.59.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.10)': dependencies: - '@vitest/browser': 4.1.8(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.8) - '@vitest/mocker': 4.1.8(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/browser': 4.1.10(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.10) + '@vitest/mocker': 4.1.10(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) playwright: 1.59.0 tinyrainbow: 3.1.0 - vitest: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) transitivePeerDependencies: - bufferutil - msw @@ -19882,30 +20420,30 @@ snapshots: - vite optional: true - '@vitest/browser-playwright@4.1.8(playwright@1.59.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.8)': + '@vitest/browser-playwright@4.1.10(playwright@1.59.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.10)': dependencies: - '@vitest/browser': 4.1.8(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.8) - '@vitest/mocker': 4.1.8(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/browser': 4.1.10(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.10) + '@vitest/mocker': 4.1.10(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) playwright: 1.59.0 tinyrainbow: 3.1.0 - vitest: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) transitivePeerDependencies: - bufferutil - msw - utf-8-validate - vite - '@vitest/browser@4.1.8(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.8)': + '@vitest/browser@4.1.10(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.10)': dependencies: '@blazediff/core': 1.9.1 - '@vitest/mocker': 4.1.8(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - '@vitest/utils': 4.1.8 + '@vitest/mocker': 4.1.10(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/utils': 4.1.10 magic-string: 0.30.21 pngjs: 7.0.0 sirv: 3.0.2 tinyrainbow: 3.1.0 - vitest: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - ws: 8.21.0 + vitest: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) + ws: 8.21.1 transitivePeerDependencies: - bufferutil - msw @@ -19913,24 +20451,41 @@ snapshots: - vite optional: true - '@vitest/browser@4.1.8(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.8)': + '@vitest/browser@4.1.10(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.10)': + dependencies: + '@blazediff/core': 1.9.1 + '@vitest/mocker': 4.1.10(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/utils': 4.1.10 + magic-string: 0.30.21 + pngjs: 7.0.0 + sirv: 3.0.2 + tinyrainbow: 3.1.0 + vitest: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) + ws: 8.21.1 + transitivePeerDependencies: + - bufferutil + - msw + - utf-8-validate + - vite + + '@vitest/browser@4.1.10(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.10)': dependencies: '@blazediff/core': 1.9.1 - '@vitest/mocker': 4.1.8(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - '@vitest/utils': 4.1.8 + '@vitest/mocker': 4.1.10(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/utils': 4.1.10 magic-string: 0.30.21 pngjs: 7.0.0 sirv: 3.0.2 tinyrainbow: 3.1.0 - vitest: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - ws: 8.21.0 + vitest: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) + ws: 8.21.1 transitivePeerDependencies: - bufferutil - msw - utf-8-validate - vite - '@vitest/coverage-istanbul@4.1.8(supports-color@8.1.1)(vitest@4.1.8)': + '@vitest/coverage-istanbul@4.1.10(supports-color@8.1.1)(vitest@4.1.10)': dependencies: '@babel/core': 7.29.6(supports-color@8.1.1) '@istanbuljs/schema': 0.1.3 @@ -19942,11 +20497,11 @@ snapshots: magicast: 0.5.2 obug: 2.1.1 tinyrainbow: 3.1.0 - vitest: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) transitivePeerDependencies: - supports-color - '@vitest/coverage-istanbul@4.1.8(vitest@4.1.8)': + '@vitest/coverage-istanbul@4.1.10(vitest@4.1.10)': dependencies: '@babel/core': 7.29.6(supports-color@8.1.1) '@istanbuljs/schema': 0.1.3 @@ -19958,7 +20513,7 @@ snapshots: magicast: 0.5.2 obug: 2.1.1 tinyrainbow: 3.1.0 - vitest: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) transitivePeerDependencies: - supports-color @@ -19970,48 +20525,56 @@ snapshots: chai: 5.3.3 tinyrainbow: 2.0.0 - '@vitest/expect@4.1.8': + '@vitest/expect@4.1.10': dependencies: '@standard-schema/spec': 1.1.0 '@types/chai': 5.2.3 - '@vitest/spy': 4.1.8 - '@vitest/utils': 4.1.8 + '@vitest/spy': 4.1.10 + '@vitest/utils': 4.1.10 chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.8(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': + '@vitest/mocker@4.1.10(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))': dependencies: - '@vitest/spy': 4.1.8 + '@vitest/spy': 4.1.10 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) - '@vitest/mocker@4.1.8(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))': + '@vitest/mocker@4.1.10(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))': dependencies: - '@vitest/spy': 4.1.8 + '@vitest/spy': 4.1.10 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) + + '@vitest/mocker@4.1.10(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))': + dependencies: + '@vitest/spy': 4.1.10 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) '@vitest/pretty-format@3.2.4': dependencies: tinyrainbow: 2.0.0 - '@vitest/pretty-format@4.1.8': + '@vitest/pretty-format@4.1.10': dependencies: tinyrainbow: 3.1.0 - '@vitest/runner@4.1.8': + '@vitest/runner@4.1.10': dependencies: - '@vitest/utils': 4.1.8 + '@vitest/utils': 4.1.10 pathe: 2.0.3 - '@vitest/snapshot@4.1.8': + '@vitest/snapshot@4.1.10': dependencies: - '@vitest/pretty-format': 4.1.8 - '@vitest/utils': 4.1.8 + '@vitest/pretty-format': 4.1.10 + '@vitest/utils': 4.1.10 magic-string: 0.30.21 pathe: 2.0.3 @@ -20019,7 +20582,7 @@ snapshots: dependencies: tinyspy: 4.0.4 - '@vitest/spy@4.1.8': {} + '@vitest/spy@4.1.10': {} '@vitest/utils@3.2.4': dependencies: @@ -20027,9 +20590,9 @@ snapshots: loupe: 3.2.1 tinyrainbow: 2.0.0 - '@vitest/utils@4.1.8': + '@vitest/utils@4.1.10': dependencies: - '@vitest/pretty-format': 4.1.8 + '@vitest/pretty-format': 4.1.10 convert-source-map: 2.0.0 tinyrainbow: 3.1.0 @@ -20170,9 +20733,9 @@ snapshots: dependencies: acorn: 8.16.0 - acorn-import-phases@1.0.4(acorn@8.16.0): + acorn-import-phases@1.0.4(acorn@8.17.0): dependencies: - acorn: 8.16.0 + acorn: 8.17.0 acorn-jsx@5.3.2(acorn@8.16.0): dependencies: @@ -20184,10 +20747,18 @@ snapshots: acorn@8.16.0: {} + acorn@8.17.0: {} + address@1.2.2: {} adm-zip@0.5.16: {} + agent-base@6.0.2(supports-color@8.1.1): + dependencies: + debug: 4.4.3(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + agent-base@7.1.4: {} aggregate-error@3.1.0: @@ -20207,13 +20778,17 @@ snapshots: optionalDependencies: ajv: 8.18.0 + ajv-formats@2.1.1(ajv@8.20.0): + optionalDependencies: + ajv: 8.20.0 + ajv-keywords@3.5.2(ajv@6.14.0): dependencies: ajv: 6.14.0 - ajv-keywords@5.1.0(ajv@8.18.0): + ajv-keywords@5.1.0(ajv@8.20.0): dependencies: - ajv: 8.18.0 + ajv: 8.20.0 fast-deep-equal: 3.1.3 ajv@6.14.0: @@ -20226,7 +20801,14 @@ snapshots: ajv@8.18.0: dependencies: fast-deep-equal: 3.1.3 - fast-uri: 4.0.1 + fast-uri: 4.1.1 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + ajv@8.20.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 4.1.1 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 @@ -20346,9 +20928,9 @@ snapshots: normalize-path: 3.0.0 picomatch: 4.0.4 - apollo-link-rest@0.9.0(@apollo/client@3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(graphql@16.12.0)(qs@6.15.2): + apollo-link-rest@0.9.0(@apollo/client@3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(graphql@16.12.0)(qs@6.15.2): dependencies: - '@apollo/client': 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@apollo/client': 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) graphql: 16.12.0 qs: 6.15.2 @@ -20499,20 +21081,22 @@ snapshots: axe-core@4.11.0: {} - axios@1.16.0: + axios@1.18.0(supports-color@8.1.1): dependencies: follow-redirects: 1.16.0(debug@4.4.3) form-data: 4.0.6 + https-proxy-agent: 5.0.1(supports-color@8.1.1) proxy-from-env: 2.1.0 transitivePeerDependencies: - debug + - supports-color azurite@3.35.0(supports-color@8.1.1): dependencies: '@azure/ms-rest-js': 1.11.2 applicationinsights: 2.9.8 args: 5.0.3 - axios: 1.16.0 + axios: 1.18.0(supports-color@8.1.1) etag: 1.8.1 express: 4.22.2 fs-extra: 11.3.2 @@ -20546,12 +21130,12 @@ snapshots: b4a@1.7.3: {} - babel-loader@9.2.1(@babel/core@7.29.6)(webpack@5.105.4(esbuild@0.28.1)): + babel-loader@9.2.1(@babel/core@7.29.6)(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)): dependencies: '@babel/core': 7.29.6(supports-color@8.1.1) find-cache-dir: 4.0.0 schema-utils: 4.3.3 - webpack: 5.105.4(esbuild@0.28.1) + webpack: 5.105.4(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10) babel-plugin-dynamic-import-node@2.3.3: dependencies: @@ -20559,7 +21143,7 @@ snapshots: babel-plugin-polyfill-corejs2@0.4.14(@babel/core@7.29.6): dependencies: - '@babel/compat-data': 7.29.0 + '@babel/compat-data': 7.29.7 '@babel/core': 7.29.6(supports-color@8.1.1) '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.29.6) semver: 6.3.1 @@ -20593,6 +21177,8 @@ snapshots: baseline-browser-mapping@2.10.0: {} + baseline-browser-mapping@2.10.43: {} + basic-auth@2.0.1: dependencies: safe-buffer: 5.1.2 @@ -20735,6 +21321,14 @@ snapshots: node-releases: 2.0.27 update-browserslist-db: 1.2.3(browserslist@4.28.1) + browserslist@4.28.6: + dependencies: + baseline-browser-mapping: 2.10.43 + caniuse-lite: 1.0.30001806 + electron-to-chromium: 1.5.393 + node-releases: 2.0.51 + update-browserslist-db: 1.2.3(browserslist@4.28.6) + bser@2.1.1: dependencies: node-int64: 0.4.0 @@ -20749,7 +21343,7 @@ snapshots: buffer-image-size@0.6.4: dependencies: - '@types/node': 24.10.1 + '@types/node': 26.1.1 buffer-xor@1.0.3: {} @@ -20858,6 +21452,8 @@ snapshots: caniuse-lite@1.0.30001777: {} + caniuse-lite@1.0.30001806: {} + capital-case@1.0.4: dependencies: no-case: 3.0.4 @@ -20869,7 +21465,7 @@ snapshots: chai@5.3.3: dependencies: assertion-error: 2.0.1 - check-error: 2.1.1 + check-error: 2.1.3 deep-eql: 5.0.2 loupe: 3.2.1 pathval: 2.0.1 @@ -20929,7 +21525,7 @@ snapshots: chardet@2.1.1: {} - check-error@2.1.1: {} + check-error@2.1.3: {} cheerio-select@2.1.0: dependencies: @@ -21191,7 +21787,7 @@ snapshots: copy-text-to-clipboard@3.2.2: {} - copy-webpack-plugin@11.0.0(webpack@5.105.4(esbuild@0.28.1)): + copy-webpack-plugin@11.0.0(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)): dependencies: fast-glob: 3.3.3 glob-parent: 6.0.2 @@ -21199,7 +21795,7 @@ snapshots: normalize-path: 3.0.0 schema-utils: 4.3.3 serialize-javascript: 7.0.5 - webpack: 5.105.4(esbuild@0.28.1) + webpack: 5.105.4(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10) core-js-compat@3.47.0: dependencies: @@ -21298,7 +21894,7 @@ snapshots: postcss-selector-parser: 7.1.1 postcss-value-parser: 4.2.0 - css-loader@6.11.0(webpack@5.105.4(esbuild@0.28.1)): + css-loader@6.11.0(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)): dependencies: icss-utils: 5.1.0(postcss@8.5.10) postcss: 8.5.10 @@ -21309,9 +21905,9 @@ snapshots: postcss-value-parser: 4.2.0 semver: 7.7.4 optionalDependencies: - webpack: 5.105.4(esbuild@0.28.1) + webpack: 5.105.4(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10) - css-minimizer-webpack-plugin@5.0.1(clean-css@5.3.3)(esbuild@0.28.1)(webpack@5.105.4(esbuild@0.28.1)): + css-minimizer-webpack-plugin@5.0.1(clean-css@5.3.3)(esbuild@0.28.1)(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)): dependencies: '@jridgewell/trace-mapping': 0.3.31 cssnano: 6.1.2(postcss@8.5.10) @@ -21319,7 +21915,7 @@ snapshots: postcss: 8.5.10 schema-utils: 4.3.3 serialize-javascript: 7.0.5 - webpack: 5.105.4(esbuild@0.28.1) + webpack: 5.105.4(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10) optionalDependencies: clean-css: 5.3.3 esbuild: 0.28.1 @@ -21489,7 +22085,7 @@ snapshots: default-browser-id@5.0.1: {} - default-browser@5.4.0: + default-browser@5.5.0: dependencies: bundle-name: 4.1.0 default-browser-id: 5.0.1 @@ -21669,6 +22265,8 @@ snapshots: electron-to-chromium@1.5.307: {} + electron-to-chromium@1.5.393: {} + elliptic@6.6.1: dependencies: bn.js: 4.12.3 @@ -21701,10 +22299,10 @@ snapshots: encodeurl@2.0.0: {} - enhanced-resolve@5.20.0: + enhanced-resolve@5.24.3: dependencies: graceful-fs: 4.2.11 - tapable: 2.3.0 + tapable: 2.3.3 entities@2.2.0: {} @@ -21801,16 +22399,22 @@ snapshots: es-module-lexer@2.0.0: {} + es-module-lexer@2.3.1: {} + es-object-atoms@1.1.1: dependencies: es-errors: 1.3.0 + es-object-atoms@1.1.2: + dependencies: + es-errors: 1.3.0 + es-set-tostringtag@2.1.0: dependencies: es-errors: 1.3.0 get-intrinsic: 1.3.0 has-tostringtag: 1.0.2 - hasown: 2.0.2 + hasown: 2.0.4 es-to-primitive@1.3.0: dependencies: @@ -21929,7 +22533,7 @@ snapshots: estree-walker@3.0.3: dependencies: - '@types/estree': 1.0.8 + '@types/estree': 1.0.9 esutils@2.0.3: {} @@ -22051,7 +22655,7 @@ snapshots: fast-json-stable-stringify@2.1.0: {} - fast-uri@4.0.1: {} + fast-uri@4.1.1: {} fast-xml-builder@1.2.0: dependencies: @@ -22076,7 +22680,7 @@ snapshots: faye-websocket@0.11.4: dependencies: - websocket-driver: 0.7.4 + websocket-driver: 0.7.5 fb-watchman@2.0.2: dependencies: @@ -22100,9 +22704,9 @@ snapshots: dependencies: walk-up-path: 4.0.0 - fdir@6.5.0(picomatch@4.0.4): + fdir@6.5.0(picomatch@4.0.5): optionalDependencies: - picomatch: 4.0.4 + picomatch: 4.0.5 fecha@4.2.3: {} @@ -22123,11 +22727,11 @@ snapshots: dependencies: is-unicode-supported: 2.1.0 - file-loader@6.2.0(webpack@5.105.4(esbuild@0.28.1)): + file-loader@6.2.0(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)): dependencies: loader-utils: 2.0.4 schema-utils: 3.3.0 - webpack: 5.105.4(esbuild@0.28.1) + webpack: 5.105.4(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10) filename-reserved-regex@2.0.0: {} @@ -22286,7 +22890,7 @@ snapshots: call-bind-apply-helpers: 1.0.2 es-define-property: 1.0.1 es-errors: 1.3.0 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 function-bind: 1.1.2 get-proto: 1.0.1 gopd: 1.2.0 @@ -22299,7 +22903,7 @@ snapshots: get-proto@1.0.1: dependencies: dunder-proto: 1.0.1 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 get-stdin@8.0.0: {} @@ -22316,7 +22920,7 @@ snapshots: es-errors: 1.3.0 get-intrinsic: 1.3.0 - get-tsconfig@4.13.0: + get-tsconfig@4.14.0: dependencies: resolve-pkg-maps: 1.0.0 @@ -22492,11 +23096,11 @@ snapshots: graphql: 16.12.0 tslib: 2.8.1 - graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.0): + graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.1): dependencies: graphql: 16.12.0 optionalDependencies: - ws: 8.21.0 + ws: 8.21.1 graphql@14.7.0: dependencies: @@ -22519,13 +23123,13 @@ snapshots: happy-dom@20.10.1: dependencies: - '@types/node': 24.10.1 + '@types/node': 26.1.1 '@types/whatwg-mimetype': 3.0.2 '@types/ws': 8.18.1 buffer-image-size: 0.6.4 entities: 7.0.1 whatwg-mimetype: 3.0.0 - ws: 8.21.0 + ws: 8.21.1 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -22744,7 +23348,7 @@ snapshots: html-void-elements@3.0.0: {} - html-webpack-plugin@5.6.5(webpack@5.105.4(esbuild@0.28.1)): + html-webpack-plugin@5.6.5(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)): dependencies: '@types/html-minifier-terser': 6.1.0 html-minifier-terser: 6.1.0 @@ -22752,7 +23356,7 @@ snapshots: pretty-error: 4.0.0 tapable: 2.3.0 optionalDependencies: - webpack: 5.105.4(esbuild@0.28.1) + webpack: 5.105.4(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10) htmlparser2@6.1.0: dependencies: @@ -22830,6 +23434,13 @@ snapshots: https-browserify@1.0.0: {} + https-proxy-agent@5.0.1(supports-color@8.1.1): + dependencies: + agent-base: 6.0.2(supports-color@8.1.1) + debug: 4.4.3(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + https-proxy-agent@7.0.6: dependencies: agent-base: 7.1.4 @@ -23176,7 +23787,7 @@ snapshots: dependencies: is-docker: 2.2.1 - is-wsl@3.1.0: + is-wsl@3.1.1: dependencies: is-inside-container: 1.0.0 @@ -23196,9 +23807,9 @@ snapshots: isomorphic-timers-promises@1.0.1: {} - isomorphic-ws@5.0.0(ws@8.21.0): + isomorphic-ws@5.0.0(ws@8.21.1): dependencies: - ws: 8.21.0 + ws: 8.21.1 istanbul-lib-coverage@3.2.2: {} @@ -23236,7 +23847,7 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 24.10.1 + '@types/node': 26.1.1 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -23283,7 +23894,7 @@ snapshots: http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.22 + nwsapi: 2.2.24 parse5: 7.3.0 rrweb-cssom: 0.8.0 saxes: 6.0.0 @@ -23294,7 +23905,7 @@ snapshots: whatwg-encoding: 3.1.1 whatwg-mimetype: 4.0.0 whatwg-url: 14.2.0 - ws: 8.21.0 + ws: 8.21.1 xml-name-validator: 5.0.0 transitivePeerDependencies: - bufferutil @@ -23435,7 +24046,7 @@ snapshots: image-size: 0.5.5 make-dir: 2.1.0 mime: 1.6.0 - needle: 3.3.1 + needle: 3.5.0 source-map: 0.6.1 leven@2.1.0: {} @@ -23446,54 +24057,54 @@ snapshots: dependencies: immediate: 3.0.6 - lightningcss-android-arm64@1.32.0: + lightningcss-android-arm64@1.33.0: optional: true - lightningcss-darwin-arm64@1.32.0: + lightningcss-darwin-arm64@1.33.0: optional: true - lightningcss-darwin-x64@1.32.0: + lightningcss-darwin-x64@1.33.0: optional: true - lightningcss-freebsd-x64@1.32.0: + lightningcss-freebsd-x64@1.33.0: optional: true - lightningcss-linux-arm-gnueabihf@1.32.0: + lightningcss-linux-arm-gnueabihf@1.33.0: optional: true - lightningcss-linux-arm64-gnu@1.32.0: + lightningcss-linux-arm64-gnu@1.33.0: optional: true - lightningcss-linux-arm64-musl@1.32.0: + lightningcss-linux-arm64-musl@1.33.0: optional: true - lightningcss-linux-x64-gnu@1.32.0: + lightningcss-linux-x64-gnu@1.33.0: optional: true - lightningcss-linux-x64-musl@1.32.0: + lightningcss-linux-x64-musl@1.33.0: optional: true - lightningcss-win32-arm64-msvc@1.32.0: + lightningcss-win32-arm64-msvc@1.33.0: optional: true - lightningcss-win32-x64-msvc@1.32.0: + lightningcss-win32-x64-msvc@1.33.0: optional: true - lightningcss@1.32.0: + lightningcss@1.33.0: dependencies: detect-libc: 2.1.2 optionalDependencies: - lightningcss-android-arm64: 1.32.0 - lightningcss-darwin-arm64: 1.32.0 - lightningcss-darwin-x64: 1.32.0 - lightningcss-freebsd-x64: 1.32.0 - lightningcss-linux-arm-gnueabihf: 1.32.0 - lightningcss-linux-arm64-gnu: 1.32.0 - lightningcss-linux-arm64-musl: 1.32.0 - lightningcss-linux-x64-gnu: 1.32.0 - lightningcss-linux-x64-musl: 1.32.0 - lightningcss-win32-arm64-msvc: 1.32.0 - lightningcss-win32-x64-msvc: 1.32.0 + lightningcss-android-arm64: 1.33.0 + lightningcss-darwin-arm64: 1.33.0 + lightningcss-darwin-x64: 1.33.0 + lightningcss-freebsd-x64: 1.33.0 + lightningcss-linux-arm-gnueabihf: 1.33.0 + lightningcss-linux-arm64-gnu: 1.33.0 + lightningcss-linux-arm64-musl: 1.33.0 + lightningcss-linux-x64-gnu: 1.33.0 + lightningcss-linux-x64-musl: 1.33.0 + lightningcss-win32-arm64-msvc: 1.33.0 + lightningcss-win32-x64-msvc: 1.33.0 lilconfig@3.1.3: {} @@ -23510,7 +24121,7 @@ snapshots: through: 2.3.8 wrap-ansi: 7.0.0 - loader-runner@4.3.1: {} + loader-runner@4.3.2: {} loader-utils@2.0.4: dependencies: @@ -23639,8 +24250,8 @@ snapshots: magicast@0.5.2: dependencies: - '@babel/parser': 7.29.2 - '@babel/types': 7.29.0 + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 source-map-js: 1.2.1 make-dir@2.1.0: @@ -23655,7 +24266,7 @@ snapshots: make-dir@4.0.0: dependencies: - semver: 7.7.4 + semver: 7.8.0 map-cache@0.2.2: {} @@ -24231,11 +24842,11 @@ snapshots: min-indent@1.0.1: {} - mini-css-extract-plugin@2.9.4(webpack@5.105.4(esbuild@0.28.1)): + mini-css-extract-plugin@2.9.4(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)): dependencies: schema-utils: 4.3.3 tapable: 2.3.0 - webpack: 5.105.4(esbuild@0.28.1) + webpack: 5.105.4(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10) minimalistic-assert@1.0.1: {} @@ -24451,14 +25062,14 @@ snapshots: dependencies: lru-cache: 7.18.3 - nanoid@3.3.11: {} + nanoid@3.3.16: {} native-duplexpair@1.0.0: {} - needle@3.3.1: + needle@3.5.0: dependencies: iconv-lite: 0.6.3 - sax: 1.5.0 + sax: 1.6.0 optional: true negotiator@0.6.3: {} @@ -24509,6 +25120,8 @@ snapshots: node-releases@2.0.27: {} + node-releases@2.0.51: {} + node-stdlib-browser@1.3.1: dependencies: assert: 2.1.0 @@ -24578,15 +25191,15 @@ snapshots: dependencies: boolbase: 1.0.0 - null-loader@4.0.1(webpack@5.105.4(esbuild@0.28.1)): + null-loader@4.0.1(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)): dependencies: loader-utils: 2.0.4 schema-utils: 3.3.0 - webpack: 5.105.4(esbuild@0.28.1) + webpack: 5.105.4(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10) nullthrows@1.1.1: {} - nwsapi@2.2.22: {} + nwsapi@2.2.24: {} object-assign@4.1.1: {} @@ -24642,7 +25255,7 @@ snapshots: open@10.2.0: dependencies: - default-browser: 5.4.0 + default-browser: 5.5.0 define-lazy-prop: 3.0.0 is-inside-container: 1.0.0 wsl-utils: 0.1.0 @@ -24760,27 +25373,27 @@ snapshots: - '@emnapi/core' - '@emnapi/runtime' - oxc-resolver@11.20.0: + oxc-resolver@11.24.2: optionalDependencies: - '@oxc-resolver/binding-android-arm-eabi': 11.20.0 - '@oxc-resolver/binding-android-arm64': 11.20.0 - '@oxc-resolver/binding-darwin-arm64': 11.20.0 - '@oxc-resolver/binding-darwin-x64': 11.20.0 - '@oxc-resolver/binding-freebsd-x64': 11.20.0 - '@oxc-resolver/binding-linux-arm-gnueabihf': 11.20.0 - '@oxc-resolver/binding-linux-arm-musleabihf': 11.20.0 - '@oxc-resolver/binding-linux-arm64-gnu': 11.20.0 - '@oxc-resolver/binding-linux-arm64-musl': 11.20.0 - '@oxc-resolver/binding-linux-ppc64-gnu': 11.20.0 - '@oxc-resolver/binding-linux-riscv64-gnu': 11.20.0 - '@oxc-resolver/binding-linux-riscv64-musl': 11.20.0 - '@oxc-resolver/binding-linux-s390x-gnu': 11.20.0 - '@oxc-resolver/binding-linux-x64-gnu': 11.20.0 - '@oxc-resolver/binding-linux-x64-musl': 11.20.0 - '@oxc-resolver/binding-openharmony-arm64': 11.20.0 - '@oxc-resolver/binding-wasm32-wasi': 11.20.0 - '@oxc-resolver/binding-win32-arm64-msvc': 11.20.0 - '@oxc-resolver/binding-win32-x64-msvc': 11.20.0 + '@oxc-resolver/binding-android-arm-eabi': 11.24.2 + '@oxc-resolver/binding-android-arm64': 11.24.2 + '@oxc-resolver/binding-darwin-arm64': 11.24.2 + '@oxc-resolver/binding-darwin-x64': 11.24.2 + '@oxc-resolver/binding-freebsd-x64': 11.24.2 + '@oxc-resolver/binding-linux-arm-gnueabihf': 11.24.2 + '@oxc-resolver/binding-linux-arm-musleabihf': 11.24.2 + '@oxc-resolver/binding-linux-arm64-gnu': 11.24.2 + '@oxc-resolver/binding-linux-arm64-musl': 11.24.2 + '@oxc-resolver/binding-linux-ppc64-gnu': 11.24.2 + '@oxc-resolver/binding-linux-riscv64-gnu': 11.24.2 + '@oxc-resolver/binding-linux-riscv64-musl': 11.24.2 + '@oxc-resolver/binding-linux-s390x-gnu': 11.24.2 + '@oxc-resolver/binding-linux-x64-gnu': 11.24.2 + '@oxc-resolver/binding-linux-x64-musl': 11.24.2 + '@oxc-resolver/binding-openharmony-arm64': 11.24.2 + '@oxc-resolver/binding-wasm32-wasi': 11.24.2 + '@oxc-resolver/binding-win32-arm64-msvc': 11.24.2 + '@oxc-resolver/binding-win32-x64-msvc': 11.24.2 p-cancelable@3.0.0: {} @@ -24992,6 +25605,8 @@ snapshots: picomatch@4.0.4: {} + picomatch@4.0.5: {} + pify@2.3.0: {} pify@4.0.1: @@ -25209,13 +25824,13 @@ snapshots: tsx: 4.21.0 yaml: 2.8.3 - postcss-loader@7.3.4(postcss@8.5.10)(typescript@6.0.3)(webpack@5.105.4(esbuild@0.28.1)): + postcss-loader@7.3.4(postcss@8.5.10)(typescript@6.0.3)(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)): dependencies: cosmiconfig: 8.3.6(typescript@6.0.3) jiti: 2.6.1 postcss: 8.5.10 semver: 7.7.4 - webpack: 5.105.4(esbuild@0.28.1) + webpack: 5.105.4(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10) transitivePeerDependencies: - typescript @@ -25490,7 +26105,7 @@ snapshots: dependencies: postcss: 8.5.10 postcss-value-parser: 4.2.0 - svgo: 3.3.3 + svgo: 3.3.4 postcss-unique-selectors@6.0.4(postcss@8.5.10): dependencies: @@ -25505,7 +26120,7 @@ snapshots: postcss@8.5.10: dependencies: - nanoid: 3.3.11 + nanoid: 3.3.16 picocolors: 1.1.1 source-map-js: 1.2.1 @@ -25620,7 +26235,7 @@ snapshots: qs@6.15.2: dependencies: - side-channel: 1.1.0 + side-channel: 1.1.1 querystring-es3@0.2.1: {} @@ -25709,11 +26324,11 @@ snapshots: dependencies: react: 19.2.0 - react-loadable-ssr-addon-v5-slorber@1.0.3(@docusaurus/react-loadable@6.0.0(react@19.2.0))(webpack@5.105.4(esbuild@0.28.1)): + react-loadable-ssr-addon-v5-slorber@1.0.3(@docusaurus/react-loadable@6.0.0(react@19.2.0))(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)): dependencies: '@babel/runtime': 7.28.4 react-loadable: '@docusaurus/react-loadable@6.0.0(react@19.2.0)' - webpack: 5.105.4(esbuild@0.28.1) + webpack: 5.105.4(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10) react-oidc-context@3.3.0(oidc-client-ts@3.4.1)(react@19.2.0): dependencies: @@ -25817,7 +26432,7 @@ snapshots: dependencies: picomatch: 4.0.4 - recast@0.23.11: + recast@0.23.12: dependencies: ast-types: 0.16.1 esprima: 4.0.1 @@ -25867,7 +26482,7 @@ snapshots: define-properties: 1.2.1 es-abstract: 1.24.0 es-errors: 1.3.0 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 get-intrinsic: 1.3.0 get-proto: 1.0.1 which-builtin-type: 1.2.1 @@ -25939,7 +26554,7 @@ snapshots: relay-runtime@12.0.0: dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.29.7 fbjs: 3.0.5 invariant: 2.2.4 transitivePeerDependencies: @@ -26131,6 +26746,28 @@ snapshots: - '@emnapi/core' - '@emnapi/runtime' + rolldown@1.0.0-beta.55(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2): + dependencies: + '@oxc-project/types': 0.103.0 + '@rolldown/pluginutils': 1.0.0-beta.55 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.0.0-beta.55 + '@rolldown/binding-darwin-arm64': 1.0.0-beta.55 + '@rolldown/binding-darwin-x64': 1.0.0-beta.55 + '@rolldown/binding-freebsd-x64': 1.0.0-beta.55 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-beta.55 + '@rolldown/binding-linux-arm64-gnu': 1.0.0-beta.55 + '@rolldown/binding-linux-arm64-musl': 1.0.0-beta.55 + '@rolldown/binding-linux-x64-gnu': 1.0.0-beta.55 + '@rolldown/binding-linux-x64-musl': 1.0.0-beta.55 + '@rolldown/binding-openharmony-arm64': 1.0.0-beta.55 + '@rolldown/binding-wasm32-wasi': 1.0.0-beta.55(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) + '@rolldown/binding-win32-arm64-msvc': 1.0.0-beta.55 + '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.55 + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' + rolldown@1.0.3: dependencies: '@oxc-project/types': 0.133.0 @@ -26211,6 +26848,9 @@ snapshots: sax@1.5.0: {} + sax@1.6.0: + optional: true + saxes@6.0.0: dependencies: xmlchars: 2.2.0 @@ -26228,9 +26868,9 @@ snapshots: schema-utils@4.3.3: dependencies: '@types/json-schema': 7.0.15 - ajv: 8.18.0 - ajv-formats: 2.1.1(ajv@8.18.0) - ajv-keywords: 5.1.0(ajv@8.18.0) + ajv: 8.20.0 + ajv-formats: 2.1.1(ajv@8.20.0) + ajv-keywords: 5.1.0(ajv@8.20.0) scroll-into-view-if-needed@3.1.0: dependencies: @@ -26272,6 +26912,8 @@ snapshots: semver@7.8.0: {} + semver@7.8.5: {} + send@0.19.0: dependencies: debug: 2.6.9 @@ -26418,6 +27060,11 @@ snapshots: es-errors: 1.3.0 object-inspect: 1.13.4 + side-channel-list@1.0.1: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-map@1.0.1: dependencies: call-bound: 1.0.4 @@ -26441,6 +27088,14 @@ snapshots: side-channel-map: 1.0.1 side-channel-weakmap: 1.0.2 + side-channel@1.1.1: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.1 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + sift@17.1.3: {} siginfo@2.0.0: {} @@ -26512,7 +27167,7 @@ snapshots: dependencies: faye-websocket: 0.11.4 uuid: 8.3.2 - websocket-driver: 0.7.4 + websocket-driver: 0.7.5 sort-css-media-queries@2.2.0: {} @@ -26613,16 +27268,16 @@ snapshots: stoppable@1.1.0: {} - storybook-addon-apollo-client@9.0.0(@apollo/client@3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(graphql@16.12.0)(react@19.2.0): + storybook-addon-apollo-client@9.0.0(@apollo/client@3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(graphql@16.12.0)(react@19.2.0): dependencies: - '@apollo/client': 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.0))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@apollo/client': 3.14.0(@types/react@19.2.7)(graphql-ws@6.0.6(graphql@16.12.0)(ws@8.21.1))(graphql@16.12.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) graphql: 16.12.0 react: 19.2.0 - storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0): + storybook@10.4.2(@testing-library/dom@10.4.1)(@types/react@19.2.7)(react@19.2.0): dependencies: '@storybook/global': 5.0.0 - '@storybook/icons': 2.0.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@storybook/icons': 2.1.0(react@19.2.0) '@testing-library/jest-dom': 6.9.1 '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.1) '@vitest/expect': 3.2.4 @@ -26631,18 +27286,17 @@ snapshots: esbuild: 0.28.1 open: 10.2.0 oxc-parser: 0.127.0 - oxc-resolver: 11.20.0 - recast: 0.23.11 - semver: 7.8.0 + oxc-resolver: 11.24.2 + recast: 0.23.12 + semver: 7.8.5 use-sync-external-store: 1.6.0(react@19.2.0) - ws: 8.21.0 + ws: 8.21.1 optionalDependencies: '@types/react': 19.2.7 transitivePeerDependencies: - '@testing-library/dom' - bufferutil - react - - react-dom - utf-8-validate stream-browserify@3.0.0: @@ -26788,7 +27442,7 @@ snapshots: lines-and-columns: 1.2.4 mz: 2.7.0 pirates: 4.0.7 - tinyglobby: 0.2.15 + tinyglobby: 0.2.17 ts-interface-checker: 0.1.13 supports-color@5.5.0: @@ -26807,7 +27461,7 @@ snapshots: svg-parser@2.0.4: {} - svgo@3.3.3: + svgo@3.3.4: dependencies: commander: 7.2.0 css-select: 5.2.2 @@ -26869,6 +27523,8 @@ snapshots: tapable@2.3.0: {} + tapable@2.3.3: {} + tar-stream@3.1.7: dependencies: b4a: 1.7.3 @@ -26894,15 +27550,40 @@ snapshots: transitivePeerDependencies: - supports-color - terser-webpack-plugin@5.4.0(esbuild@0.28.1)(webpack@5.105.4(esbuild@0.28.1)): + terser-webpack-plugin@5.4.0(esbuild@0.28.1)(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)): dependencies: '@jridgewell/trace-mapping': 0.3.31 jest-worker: 27.5.1 schema-utils: 4.3.3 terser: 5.44.1 + webpack: 5.105.4(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10) + optionalDependencies: + esbuild: 0.28.1 + + terser-webpack-plugin@5.6.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)): + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + jest-worker: 27.5.1 + schema-utils: 4.3.3 + terser: 5.49.0 + webpack: 5.105.4(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10) + optionalDependencies: + clean-css: 5.3.3 + cssnano: 6.1.2(postcss@8.5.10) + esbuild: 0.28.1 + html-minifier-terser: 7.2.0 + postcss: 8.5.10 + + terser-webpack-plugin@5.6.1(esbuild@0.28.1)(webpack@5.105.4(esbuild@0.28.1)): + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + jest-worker: 27.5.1 + schema-utils: 4.3.3 + terser: 5.49.0 webpack: 5.105.4(esbuild@0.28.1) optionalDependencies: esbuild: 0.28.1 + optional: true terser@5.44.1: dependencies: @@ -26911,6 +27592,13 @@ snapshots: commander: 2.20.3 source-map-support: 0.5.21 + terser@5.49.0: + dependencies: + '@jridgewell/source-map': 0.3.11 + acorn: 8.17.0 + commander: 2.20.3 + source-map-support: 0.5.21 + test-exclude@7.0.2: dependencies: '@istanbuljs/schema': 0.1.3 @@ -26974,15 +27662,10 @@ snapshots: tinyexec@1.0.4: {} - tinyglobby@0.2.15: - dependencies: - fdir: 6.5.0(picomatch@4.0.4) - picomatch: 4.0.4 - tinyglobby@0.2.17: dependencies: - fdir: 6.5.0(picomatch@4.0.4) - picomatch: 4.0.4 + fdir: 6.5.0(picomatch@4.0.5) + picomatch: 4.0.5 tinypool@1.1.1: {} @@ -27094,7 +27777,7 @@ snapshots: tsx@4.21.0: dependencies: esbuild: 0.28.1 - get-tsconfig: 4.13.0 + get-tsconfig: 4.14.0 optionalDependencies: fsevents: 2.3.3 @@ -27196,6 +27879,8 @@ snapshots: undici-types@7.16.0: {} + undici-types@8.3.0: {} + unicode-canonical-property-names-ecmascript@2.0.1: {} unicode-emoji-modifier-base@1.0.0: {} @@ -27279,6 +27964,12 @@ snapshots: escalade: 3.2.0 picocolors: 1.1.1 + update-browserslist-db@1.2.3(browserslist@4.28.6): + dependencies: + browserslist: 4.28.6 + escalade: 3.2.0 + picocolors: 1.1.1 + update-notifier@6.0.2: dependencies: boxen: 7.1.1 @@ -27310,14 +28001,14 @@ snapshots: uri-templates@0.2.0: {} - url-loader@4.1.1(file-loader@6.2.0(webpack@5.105.4(esbuild@0.28.1)))(webpack@5.105.4(esbuild@0.28.1)): + url-loader@4.1.1(file-loader@6.2.0(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)))(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)): dependencies: loader-utils: 2.0.4 mime-types: 2.1.35 schema-utils: 3.3.0 - webpack: 5.105.4(esbuild@0.28.1) + webpack: 5.105.4(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10) optionalDependencies: - file-loader: 6.2.0(webpack@5.105.4(esbuild@0.28.1)) + file-loader: 6.2.0(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)) url-parse@1.5.10: dependencies: @@ -27399,18 +28090,18 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.3 - vite-plugin-node-polyfills@0.28.0(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)): + vite-plugin-node-polyfills@0.28.0(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)): dependencies: '@rollup/plugin-inject': 5.0.5 node-stdlib-browser: 1.3.1 - vite: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) transitivePeerDependencies: - rollup - vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3): + vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3): dependencies: - lightningcss: 1.32.0 - picomatch: 4.0.4 + lightningcss: 1.33.0 + picomatch: 4.0.5 postcss: 8.5.10 rolldown: 1.0.3 tinyglobby: 0.2.17 @@ -27420,14 +28111,14 @@ snapshots: fsevents: 2.3.3 jiti: 2.6.1 less: 4.4.2 - terser: 5.44.1 + terser: 5.49.0 tsx: 4.21.0 yaml: 2.8.3 - vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3): + vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3): dependencies: - lightningcss: 1.32.0 - picomatch: 4.0.4 + lightningcss: 1.33.0 + picomatch: 4.0.5 postcss: 8.5.10 rolldown: 1.0.3 tinyglobby: 0.2.17 @@ -27437,19 +28128,36 @@ snapshots: fsevents: 2.3.3 jiti: 2.6.1 less: 4.4.2 - terser: 5.44.1 + terser: 5.49.0 + tsx: 4.21.0 + yaml: 2.8.3 + + vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3): + dependencies: + lightningcss: 1.33.0 + picomatch: 4.0.5 + postcss: 8.5.10 + rolldown: 1.0.3 + tinyglobby: 0.2.17 + optionalDependencies: + '@types/node': 26.1.1 + esbuild: 0.28.1 + fsevents: 2.3.3 + jiti: 2.6.1 + less: 4.4.2 + terser: 5.49.0 tsx: 4.21.0 yaml: 2.8.3 - vitest@4.1.8(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)): + vitest@4.1.10(@opentelemetry/api@1.9.0)(@types/node@22.19.15)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)): dependencies: - '@vitest/expect': 4.1.8 - '@vitest/mocker': 4.1.8(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - '@vitest/pretty-format': 4.1.8 - '@vitest/runner': 4.1.8 - '@vitest/snapshot': 4.1.8 - '@vitest/spy': 4.1.8 - '@vitest/utils': 4.1.8 + '@vitest/expect': 4.1.10 + '@vitest/mocker': 4.1.10(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/pretty-format': 4.1.10 + '@vitest/runner': 4.1.10 + '@vitest/snapshot': 4.1.10 + '@vitest/spy': 4.1.10 + '@vitest/utils': 4.1.10 es-module-lexer: 2.0.0 expect-type: 1.3.0 magic-string: 0.30.21 @@ -27461,27 +28169,59 @@ snapshots: tinyexec: 1.0.4 tinyglobby: 0.2.17 tinyrainbow: 3.1.0 - vite: 8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) why-is-node-running: 2.3.0 optionalDependencies: '@opentelemetry/api': 1.9.0 '@types/node': 22.19.15 - '@vitest/browser-playwright': 4.1.8(playwright@1.59.0)(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.8) - '@vitest/coverage-istanbul': 4.1.8(supports-color@8.1.1)(vitest@4.1.8) + '@vitest/browser-playwright': 4.1.10(playwright@1.59.0)(vite@8.0.16(@types/node@22.19.15)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.10) + '@vitest/coverage-istanbul': 4.1.10(supports-color@8.1.1)(vitest@4.1.10) + happy-dom: 20.10.1 + jsdom: 26.1.0 + transitivePeerDependencies: + - msw + + vitest@4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)): + dependencies: + '@vitest/expect': 4.1.10 + '@vitest/mocker': 4.1.10(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/pretty-format': 4.1.10 + '@vitest/runner': 4.1.10 + '@vitest/snapshot': 4.1.10 + '@vitest/spy': 4.1.10 + '@vitest/utils': 4.1.10 + es-module-lexer: 2.0.0 + expect-type: 1.3.0 + magic-string: 0.30.21 + obug: 2.1.1 + pathe: 2.0.3 + picomatch: 4.0.4 + std-env: 4.0.0 + tinybench: 2.9.0 + tinyexec: 1.0.4 + tinyglobby: 0.2.17 + tinyrainbow: 3.1.0 + vite: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) + why-is-node-running: 2.3.0 + optionalDependencies: + '@opentelemetry/api': 1.9.0 + '@types/node': 24.10.1 + '@vitest/browser-playwright': 4.1.10(playwright@1.59.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.10) + '@vitest/coverage-istanbul': 4.1.10(vitest@4.1.10) happy-dom: 20.10.1 jsdom: 26.1.0 transitivePeerDependencies: - msw - vitest@4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.8)(@vitest/coverage-istanbul@4.1.8)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)): + vitest@4.1.10(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/browser-playwright@4.1.10)(@vitest/coverage-istanbul@4.1.10)(happy-dom@20.10.1)(jsdom@26.1.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)): dependencies: - '@vitest/expect': 4.1.8 - '@vitest/mocker': 4.1.8(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3)) - '@vitest/pretty-format': 4.1.8 - '@vitest/runner': 4.1.8 - '@vitest/snapshot': 4.1.8 - '@vitest/spy': 4.1.8 - '@vitest/utils': 4.1.8 + '@vitest/expect': 4.1.10 + '@vitest/mocker': 4.1.10(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/pretty-format': 4.1.10 + '@vitest/runner': 4.1.10 + '@vitest/snapshot': 4.1.10 + '@vitest/spy': 4.1.10 + '@vitest/utils': 4.1.10 es-module-lexer: 2.0.0 expect-type: 1.3.0 magic-string: 0.30.21 @@ -27493,13 +28233,13 @@ snapshots: tinyexec: 1.0.4 tinyglobby: 0.2.17 tinyrainbow: 3.1.0 - vite: 8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3) why-is-node-running: 2.3.0 optionalDependencies: '@opentelemetry/api': 1.9.0 '@types/node': 24.10.1 - '@vitest/browser-playwright': 4.1.8(playwright@1.59.0)(vite@8.0.16(@types/node@24.10.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.8) - '@vitest/coverage-istanbul': 4.1.8(vitest@4.1.8) + '@vitest/browser-playwright': 4.1.10(playwright@1.59.0)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.2)(terser@5.49.0)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.10) + '@vitest/coverage-istanbul': 4.1.10(vitest@4.1.10) happy-dom: 20.10.1 jsdom: 26.1.0 transitivePeerDependencies: @@ -27517,9 +28257,8 @@ snapshots: dependencies: loose-envify: 1.4.0 - watchpack@2.5.1: + watchpack@2.5.2: dependencies: - glob-to-regexp: 0.4.1 graceful-fs: 4.2.11 wbuf@1.7.3: @@ -27551,12 +28290,12 @@ snapshots: opener: 1.5.2 picocolors: 1.1.1 sirv: 2.0.4 - ws: 8.21.0 + ws: 8.21.1 transitivePeerDependencies: - bufferutil - utf-8-validate - webpack-dev-middleware@7.4.5(webpack@5.105.4(esbuild@0.28.1)): + webpack-dev-middleware@7.4.5(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)): dependencies: colorette: 2.0.20 memfs: 4.51.1 @@ -27565,9 +28304,9 @@ snapshots: range-parser: 1.2.1 schema-utils: 4.3.3 optionalDependencies: - webpack: 5.105.4(esbuild@0.28.1) + webpack: 5.105.4(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10) - webpack-dev-server@5.2.6(webpack@5.105.4(esbuild@0.28.1)): + webpack-dev-server@5.2.6(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)): dependencies: '@types/bonjour': 3.5.13 '@types/connect-history-api-fallback': 1.5.4 @@ -27595,10 +28334,10 @@ snapshots: serve-index: 1.9.1 sockjs: 0.3.24 spdy: 4.0.2 - webpack-dev-middleware: 7.4.5(webpack@5.105.4(esbuild@0.28.1)) - ws: 8.21.0 + webpack-dev-middleware: 7.4.5(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)) + ws: 8.21.1 optionalDependencies: - webpack: 5.105.4(esbuild@0.28.1) + webpack: 5.105.4(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10) transitivePeerDependencies: - bufferutil - supports-color @@ -27616,52 +28355,103 @@ snapshots: flat: 5.0.2 wildcard: 2.0.1 - webpack-sources@3.3.4: {} + webpack-sources@3.5.1: {} webpack-virtual-modules@0.6.2: {} + webpack@5.105.4(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10): + dependencies: + '@types/eslint-scope': 3.7.7 + '@types/estree': 1.0.9 + '@types/json-schema': 7.0.15 + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/wasm-edit': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 + acorn: 8.17.0 + acorn-import-phases: 1.0.4(acorn@8.17.0) + browserslist: 4.28.6 + chrome-trace-event: 1.0.4 + enhanced-resolve: 5.24.3 + es-module-lexer: 2.3.1 + eslint-scope: 5.1.1 + events: 3.3.0 + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + json-parse-even-better-errors: 2.3.1 + loader-runner: 4.3.2 + mime-types: 2.1.35 + neo-async: 2.6.2 + schema-utils: 4.3.3 + tapable: 2.3.3 + terser-webpack-plugin: 5.6.1(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10)(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)) + watchpack: 2.5.2 + webpack-sources: 3.5.1 + transitivePeerDependencies: + - '@minify-html/node' + - '@swc/core' + - '@swc/css' + - '@swc/html' + - clean-css + - cssnano + - csso + - esbuild + - html-minifier-terser + - lightningcss + - postcss + - uglify-js + webpack@5.105.4(esbuild@0.28.1): dependencies: '@types/eslint-scope': 3.7.7 - '@types/estree': 1.0.8 + '@types/estree': 1.0.9 '@types/json-schema': 7.0.15 '@webassemblyjs/ast': 1.14.1 '@webassemblyjs/wasm-edit': 1.14.1 '@webassemblyjs/wasm-parser': 1.14.1 - acorn: 8.16.0 - acorn-import-phases: 1.0.4(acorn@8.16.0) - browserslist: 4.28.1 + acorn: 8.17.0 + acorn-import-phases: 1.0.4(acorn@8.17.0) + browserslist: 4.28.6 chrome-trace-event: 1.0.4 - enhanced-resolve: 5.20.0 - es-module-lexer: 2.0.0 + enhanced-resolve: 5.24.3 + es-module-lexer: 2.3.1 eslint-scope: 5.1.1 events: 3.3.0 glob-to-regexp: 0.4.1 graceful-fs: 4.2.11 json-parse-even-better-errors: 2.3.1 - loader-runner: 4.3.1 + loader-runner: 4.3.2 mime-types: 2.1.35 neo-async: 2.6.2 schema-utils: 4.3.3 - tapable: 2.3.0 - terser-webpack-plugin: 5.4.0(esbuild@0.28.1)(webpack@5.105.4(esbuild@0.28.1)) - watchpack: 2.5.1 - webpack-sources: 3.3.4 + tapable: 2.3.3 + terser-webpack-plugin: 5.6.1(esbuild@0.28.1)(webpack@5.105.4(esbuild@0.28.1)) + watchpack: 2.5.2 + webpack-sources: 3.5.1 transitivePeerDependencies: + - '@minify-html/node' - '@swc/core' + - '@swc/css' + - '@swc/html' + - clean-css + - cssnano + - csso - esbuild + - html-minifier-terser + - lightningcss + - postcss - uglify-js + optional: true - webpackbar@7.0.0(webpack@5.105.4(esbuild@0.28.1)): + webpackbar@7.0.0(webpack@5.105.4(esbuild@0.28.1)(postcss@8.5.10)): dependencies: ansis: 3.17.0 consola: 3.4.2 pretty-time: 1.1.0 std-env: 3.10.0 optionalDependencies: - webpack: 5.105.4(esbuild@0.28.1) + webpack: 5.105.4(clean-css@5.3.3)(cssnano@6.1.2(postcss@8.5.10))(esbuild@0.28.1)(html-minifier-terser@7.2.0)(postcss@8.5.10) - websocket-driver@0.7.4: + websocket-driver@0.7.5: dependencies: http-parser-js: 0.5.10 safe-buffer: 5.2.1 @@ -27802,11 +28592,11 @@ snapshots: signal-exit: 3.0.7 typedarray-to-buffer: 3.1.5 - ws@8.21.0: {} + ws@8.21.1: {} wsl-utils@0.1.0: dependencies: - is-wsl: 3.1.0 + is-wsl: 3.1.1 xdg-basedir@5.1.0: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index d72187af9..7e6ae17aa 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -25,9 +25,9 @@ catalog: '@serenity-js/cucumber': 3.43.0 '@serenity-js/serenity-bdd': 3.43.0 '@types/node': ^22.19.5 - '@vitest/browser': 4.1.8 - '@vitest/browser-playwright': 4.1.8 - '@vitest/coverage-istanbul': 4.1.8 + '@vitest/browser': 4.1.10 + '@vitest/browser-playwright': 4.1.10 + '@vitest/coverage-istanbul': 4.1.10 antd: 6.3.5 archunit: ^2.1.63 esbuild: 0.28.1 @@ -52,7 +52,7 @@ catalog: typescript: 6.0.3 "@typescript/native-preview": 7.0.0-dev.20260428.1 vite: 8.0.16 - vitest: 4.1.8 + vitest: 4.1.10 vite-plugin-node-polyfills: ^0.28.0 auditConfig: @@ -75,10 +75,10 @@ allowBuilds: snyk: true overrides: - '@vitest/browser': 4.1.8 - '@vitest/browser-playwright': 4.1.8 + '@vitest/browser': 4.1.10 + '@vitest/browser-playwright': 4.1.10 happy-dom: 20.10.1 - axios: 1.16.0 + axios: 1.18.0 body-parser: 2.3.0 esbuild: 'catalog:' follow-redirects: ^1.16.0 @@ -93,7 +93,9 @@ overrides: 'serve-handler>minimatch': 3.1.5 'serialize-javascript@6.0.2': 7.0.5 'serialize-javascript@7.0.4': 7.0.5 - svgo: ^3.3.3 + svgo: ^3.3.4 + '@opentelemetry/propagator-jaeger': ^2.9.0 + websocket-driver: ^0.7.5 'yaml@2.8.2': 2.8.3 'yauzl@3.2.0': 3.2.1 qs: 6.15.2 @@ -116,7 +118,7 @@ overrides: postcss: 8.5.10 protobufjs: 7.6.5 ip-address: ^10.1.1 - fast-uri: ^4.0.1 + fast-uri: ^4.1.1 '@babel/plugin-transform-modules-systemjs': 7.29.4 '@babel/core': ^7.29.6 js-yaml: 4.3.0 @@ -124,7 +126,7 @@ overrides: 'shell-quote@<1.8.4': 1.8.4 '@opentelemetry/exporter-prometheus@0.57.2': 0.217.0 '@opentelemetry/core@2.7.1': 2.8.0 - ws: 8.21.0 + ws: 8.21.1 shell-quote: 1.9.0 '@grpc/grpc-js': '>=1.14.4' form-data: ^4.0.6 @@ -151,5 +153,5 @@ patchedDependencies: '@azure/functions@4.11.0': patches/@azure__functions@4.11.0.patch minimumReleaseAgeExclude: - - fast-uri@3.1.3 || 4.0.1 + - fast-uri@3.1.3 || 4.0.1 || 4.1.1 - body-parser@1.20.6 From 0c2f3b81a4ce430dee0b3d55bcf12c98f5dbc16c Mon Sep 17 00:00:00 2001 From: Henry Casper Date: Wed, 22 Jul 2026 22:31:28 -0400 Subject: [PATCH 02/10] fix: address staff role deletion review findings Apply focused fixes for failure propagation, assignment races, permission consistency, and audit attribution on top of the original staff-role deletion implementation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../src/hooks/use-staff-permissions.test.ts | 42 ++++++++++++++++ .../src/hooks/use-staff-permissions.ts | 43 +++++++++------- .../src/features/node-event-bus.feature | 14 +++--- .../src/node-event-bus.test.ts | 33 ++++++------ .../src/node-event-bus.ts | 25 ++++++---- .../mongo-repository.test.ts | 8 +-- .../src/mongoose-seedwork/mongo-repository.ts | 8 +-- .../mongo-unit-of-work.test.ts | 11 ++-- .../staff/staff-role-management.feature | 7 +++ .../contexts/user/staff-role/delete.test.ts | 10 ++-- .../src/contexts/user/staff-role/delete.ts | 3 +- .../contexts/user/staff-role/index.test.ts | 2 +- .../user/staff-user/assign-role.test.ts | 50 ++++++++++++++++++- .../contexts/user/staff-user/assign-role.ts | 49 ++++++++++++------ .../staff-user/features/assign-role.feature | 8 +++ .../user/staff-role/staff-role.test.ts | 11 ++-- .../contexts/user/staff-role/staff-role.ts | 3 +- .../domain/events/types/staff-role-deleted.ts | 1 + ...-role-deleted-reassignment.service.test.ts | 10 ++-- ...staff-role-deleted-reassignment.service.ts | 4 +- ...taff-role-deleted--reassign-staff-users.ts | 4 +- .../features/staff-role.resolvers.feature | 2 +- .../schema/types/staff-role.command-mapper.ts | 3 +- .../schema/types/staff-role.resolvers.test.ts | 7 ++- .../src/schema/types/staff-role.resolvers.ts | 6 ++- .../staff-user.domain-adapter.test.ts | 5 +- .../src/components/staff-role-create.test.tsx | 8 +++ .../src/components/staff-role-create.tsx | 38 ++++++++++---- .../components/staff-role-edit.container.tsx | 3 +- .../components/staff-roles-list.container.tsx | 2 +- 30 files changed, 293 insertions(+), 127 deletions(-) create mode 100644 apps/ui-staff/src/hooks/use-staff-permissions.test.ts diff --git a/apps/ui-staff/src/hooks/use-staff-permissions.test.ts b/apps/ui-staff/src/hooks/use-staff-permissions.test.ts new file mode 100644 index 000000000..01cab35a1 --- /dev/null +++ b/apps/ui-staff/src/hooks/use-staff-permissions.test.ts @@ -0,0 +1,42 @@ +import { describe, expect, it } from 'vitest'; +import { deriveStaffPermissions } from './use-staff-permissions.ts'; + +const makeRolePermissions = (canRemoveRole: boolean) => ({ + communityPermissions: { + canManageCommunities: false, + canManageStaffRolesAndPermissions: true, + }, + userPermissions: { + canManageUsers: false, + canAssignStaffRoles: false, + canViewStaffUsers: false, + }, + staffRolePermissions: { + canViewRoles: false, + canAddRole: false, + canEditRole: false, + canRemoveRole, + }, + financePermissions: { + canManageFinance: false, + }, + techAdminPermissions: { + canManageTechAdmin: true, + }, +}); + +describe('deriveStaffPermissions', () => { + it('does not infer role removal from broader management permissions', () => { + const permissions = deriveStaffPermissions(makeRolePermissions(false)); + + expect(permissions?.canManageStaffRolesAndPermissions).toBe(true); + expect(permissions?.canEditRole).toBe(true); + expect(permissions?.canRemoveRole).toBe(false); + }); + + it('grants role removal when the explicit permission is present', () => { + const permissions = deriveStaffPermissions(makeRolePermissions(true)); + + expect(permissions?.canRemoveRole).toBe(true); + }); +}); diff --git a/apps/ui-staff/src/hooks/use-staff-permissions.ts b/apps/ui-staff/src/hooks/use-staff-permissions.ts index 3d42e9ed0..1b9d963e2 100644 --- a/apps/ui-staff/src/hooks/use-staff-permissions.ts +++ b/apps/ui-staff/src/hooks/use-staff-permissions.ts @@ -78,6 +78,29 @@ interface StaffUserQueryResult { }; } +type RolePermissions = NonNullable['permissions']>; + +export const deriveStaffPermissions = (rolePermissions: RolePermissions | undefined): StaffPermissions | undefined => { + if (!rolePermissions) { + return undefined; + } + + const isTechAdmin = rolePermissions.techAdminPermissions.canManageTechAdmin; + return { + canManageCommunities: rolePermissions.communityPermissions.canManageCommunities || isTechAdmin, + canManageStaffRolesAndPermissions: rolePermissions.communityPermissions.canManageStaffRolesAndPermissions || isTechAdmin, + canManageUsers: rolePermissions.userPermissions.canManageUsers || isTechAdmin, + canAssignStaffRoles: rolePermissions.userPermissions.canAssignStaffRoles || isTechAdmin, + canViewStaffUsers: rolePermissions.userPermissions.canViewStaffUsers || rolePermissions.userPermissions.canManageUsers || isTechAdmin, + canManageFinance: rolePermissions.financePermissions.canManageFinance || isTechAdmin, + canManageTechAdmin: isTechAdmin, + canViewRoles: rolePermissions.staffRolePermissions.canViewRoles || rolePermissions.communityPermissions.canManageStaffRolesAndPermissions || isTechAdmin, + canAddRole: rolePermissions.staffRolePermissions.canAddRole || rolePermissions.communityPermissions.canManageStaffRolesAndPermissions || isTechAdmin, + canEditRole: rolePermissions.staffRolePermissions.canEditRole || rolePermissions.communityPermissions.canManageStaffRolesAndPermissions || isTechAdmin, + canRemoveRole: rolePermissions.staffRolePermissions.canRemoveRole, + }; +}; + export const useStaffPermissions = (): { permissions: StaffPermissions | undefined; enterpriseAppRole: string | undefined; @@ -91,25 +114,7 @@ export const useStaffPermissions = (): { const rolePermissions = data?.currentStaffUserAndCreateIfNotExists?.role?.permissions; const currentUser = data?.currentStaffUserAndCreateIfNotExists; - - // Treat a TechAdmin as an implicit manager of all sections - const isTechAdmin = rolePermissions?.techAdminPermissions?.canManageTechAdmin ?? false; - - const permissions: StaffPermissions | undefined = rolePermissions - ? { - canManageCommunities: rolePermissions.communityPermissions.canManageCommunities || isTechAdmin, - canManageStaffRolesAndPermissions: rolePermissions.communityPermissions.canManageStaffRolesAndPermissions || isTechAdmin, - canManageUsers: rolePermissions.userPermissions.canManageUsers || isTechAdmin, - canAssignStaffRoles: rolePermissions.userPermissions.canAssignStaffRoles || isTechAdmin, - canViewStaffUsers: rolePermissions.userPermissions.canViewStaffUsers || rolePermissions.userPermissions.canManageUsers || isTechAdmin, - canManageFinance: rolePermissions.financePermissions.canManageFinance || isTechAdmin, - canManageTechAdmin: isTechAdmin, - canViewRoles: rolePermissions.staffRolePermissions.canViewRoles || rolePermissions.communityPermissions.canManageStaffRolesAndPermissions || isTechAdmin, - canAddRole: rolePermissions.staffRolePermissions.canAddRole || rolePermissions.communityPermissions.canManageStaffRolesAndPermissions || isTechAdmin, - canEditRole: rolePermissions.staffRolePermissions.canEditRole || rolePermissions.communityPermissions.canManageStaffRolesAndPermissions || isTechAdmin, - canRemoveRole: rolePermissions.staffRolePermissions.canRemoveRole || rolePermissions.communityPermissions.canManageStaffRolesAndPermissions || isTechAdmin, - } - : undefined; + const permissions = deriveStaffPermissions(rolePermissions); return { permissions, diff --git a/packages/cellix/event-bus-seedwork-node/src/features/node-event-bus.feature b/packages/cellix/event-bus-seedwork-node/src/features/node-event-bus.feature index 46b5ff456..e3ae0c261 100644 --- a/packages/cellix/event-bus-seedwork-node/src/features/node-event-bus.feature +++ b/packages/cellix/event-bus-seedwork-node/src/features/node-event-bus.feature @@ -35,7 +35,7 @@ Feature: NodeEventBus Then span.setStatus should be called with ERROR And recordException should be called And the span should be ended - And the error should NOT be propagated + And the error should be propagated Scenario: dispatch catch block is triggered when broadcaster throws synchronously Given the NodeEventBusInstance singleton @@ -52,23 +52,23 @@ Feature: NodeEventBus And the event is dispatched Then all handlers should be called in the order they were registered - Scenario: Multiple handlers for the same event, one throws, errors not propagated + Scenario: Multiple handlers for the same event, one throws Given multiple handlers for the same event class When all handlers are registered and one throws And the event is dispatched - Then all handlers should be called and errors are not propagated + Then all handlers should be called and the error is propagated - Scenario: Multiple handlers for the same event, all throw, errors not propagated + Scenario: Multiple handlers for the same event, all throw Given multiple handlers for the same event class When all handlers are registered and all throw And the event is dispatched - Then all handlers should be called and errors are not propagated + Then all handlers should be called and an aggregate error is propagated - Scenario: Dispatch does not wait for handler completion + Scenario: Dispatch waits for handler completion Given a handler for an event that is asynchronous When the handler is registered And the event is dispatched - Then dispatch should resolve before the handler completes + Then dispatch should resolve after the handler completes Scenario: No handlers registered for an event When the event is dispatched diff --git a/packages/cellix/event-bus-seedwork-node/src/node-event-bus.test.ts b/packages/cellix/event-bus-seedwork-node/src/node-event-bus.test.ts index 3c0b0c447..3c224f7f4 100644 --- a/packages/cellix/event-bus-seedwork-node/src/node-event-bus.test.ts +++ b/packages/cellix/event-bus-seedwork-node/src/node-event-bus.test.ts @@ -1,10 +1,11 @@ -import { CustomDomainEventImpl } from '@cellix/domain-seedwork/domain-event'; -import { describeFeature, loadFeature } from '@amiceli/vitest-cucumber'; -import { expect, vi } from 'vitest'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; +import { describeFeature, loadFeature } from '@amiceli/vitest-cucumber'; +import { CustomDomainEventImpl } from '@cellix/domain-seedwork/domain-event'; +import { expect, vi } from 'vitest'; import { NodeEventBusInstance } from './node-event-bus.ts'; import type { AsyncHandlerMock } from './test-handler.types.ts'; + // --- Mocks for OpenTelemetry and performance --- const test = { for: describeFeature }; @@ -187,7 +188,7 @@ test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { })); }); When('the event is dispatched', async () => { - await expect(NodeEventBusInstance.dispatch(errorEvent, { test: 'fail' })).resolves.not.toThrow(); + await expect(NodeEventBusInstance.dispatch(errorEvent, { test: 'fail' })).rejects.toThrow('handler error'); }); Then('span.setStatus should be called with ERROR', () => { expect(spanMock.setStatus).toHaveBeenCalledWith(expect.objectContaining({ code: 2 })); @@ -198,8 +199,8 @@ test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { And('the span should be ended', () => { expect(spanMock.end).toHaveBeenCalled(); }); - And('the error should NOT be propagated', () => { - // Already checked by .resolves.not.toThrow() + And('the error should be propagated', () => { + // Already checked by .rejects.toThrow() }); }); @@ -248,7 +249,7 @@ test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { }; }); When('dispatch is called for an event', async () => { - await expect(NodeEventBusInstance.dispatch(TestEvent, { test: 'fail' })).resolves.not.toThrow(); + await expect(NodeEventBusInstance.dispatch(TestEvent, { test: 'fail' })).rejects.toThrow('sync broadcast error'); }); Then('span.setStatus should be called with ERROR', () => { expect(spanMock.setStatus).toHaveBeenCalledWith(expect.objectContaining({ code: 2 })); @@ -291,7 +292,7 @@ test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { }); }); - Scenario('Multiple handlers for the same event, one throws, errors not propagated', ({ Given, When, And, Then }) => { + Scenario('Multiple handlers for the same event, one throws', ({ Given, When, And, Then }) => { Given('multiple handlers for the same event class', () => { handler1 = vi.fn(() => Promise.reject(new Error('handler1 error'))); handler2 = vi.fn(async () => undefined); @@ -301,15 +302,15 @@ test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { NodeEventBusInstance.register(TestEvent, handler2); }); And('the event is dispatched', async () => { - await expect(NodeEventBusInstance.dispatch(TestEvent, { test: 'data' })).resolves.not.toThrow(); + await expect(NodeEventBusInstance.dispatch(TestEvent, { test: 'data' })).rejects.toThrow('handler1 error'); }); - Then('all handlers should be called and errors are not propagated', () => { + Then('all handlers should be called and the error is propagated', () => { expect(handler1).toHaveBeenCalledWith({ test: 'data' }); expect(handler2).toHaveBeenCalledWith({ test: 'data' }); }); }); - Scenario('Multiple handlers for the same event, all throw, errors not propagated', ({ Given, When, And, Then }) => { + Scenario('Multiple handlers for the same event, all throw', ({ Given, When, And, Then }) => { Given('multiple handlers for the same event class', () => { handler1 = vi.fn(() => Promise.reject(new Error('handler1 error'))); handler2 = vi.fn(() => Promise.reject(new Error('handler2 error'))); @@ -319,15 +320,15 @@ test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { NodeEventBusInstance.register(TestEvent, handler2); }); And('the event is dispatched', async () => { - await expect(NodeEventBusInstance.dispatch(TestEvent, { test: 'data' })).resolves.not.toThrow(); + await expect(NodeEventBusInstance.dispatch(TestEvent, { test: 'data' })).rejects.toThrow(AggregateError); }); - Then('all handlers should be called and errors are not propagated', () => { + Then('all handlers should be called and an aggregate error is propagated', () => { expect(handler1).toHaveBeenCalledWith({ test: 'data' }); expect(handler2).toHaveBeenCalledWith({ test: 'data' }); }); }); - Scenario('Dispatch does not wait for handler completion', ({ Given, When, And, Then }) => { + Scenario('Dispatch waits for handler completion', ({ Given, When, And, Then }) => { let handlerStarted = false; let handlerCompleted = false; let asyncHandler: TestEventHandler; @@ -346,11 +347,9 @@ test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { await Promise.resolve(); // allow microtasks to run expect(handlerStarted).toBe(true); await dispatchPromise; - expect(handlerCompleted).toBe(false); - await new Promise((resolve) => setTimeout(resolve, 60)); expect(handlerCompleted).toBe(true); }); - Then('dispatch should resolve before the handler completes', () => { + Then('dispatch should resolve after the handler completes', () => { // Checked in the And step above }); }); diff --git a/packages/cellix/event-bus-seedwork-node/src/node-event-bus.ts b/packages/cellix/event-bus-seedwork-node/src/node-event-bus.ts index dccd4b618..6f8cd6bb3 100644 --- a/packages/cellix/event-bus-seedwork-node/src/node-event-bus.ts +++ b/packages/cellix/event-bus-seedwork-node/src/node-event-bus.ts @@ -1,8 +1,9 @@ -import type { EventBus } from '@cellix/domain-seedwork/event-bus'; -import type { CustomDomainEvent, DomainEvent } from '@cellix/domain-seedwork/domain-event'; import EventEmitter from 'node:events'; import { performance } from 'node:perf_hooks'; -import api, { trace, type TimeInput, SpanStatusCode } from '@opentelemetry/api'; +import type { CustomDomainEvent, DomainEvent } from '@cellix/domain-seedwork/domain-event'; +import type { EventBus } from '@cellix/domain-seedwork/event-bus'; +import api, { SpanStatusCode, type TimeInput, trace } from '@opentelemetry/api'; + // import { SEMATTRS_DB_SYSTEM, SEMATTRS_DB_NAME, SEMATTRS_DB_STATEMENT } from '@opentelemetry/semantic-conventions'; // not sure where to import these from, see link below // https://github.com/open-telemetry/opentelemetry-js/blob/main/semantic-conventions/README.md#migrated-usage @@ -18,18 +19,18 @@ class BroadCaster { } public async broadcast(event: string, data: unknown): Promise { - // Collect all listeners for the event const listeners = this.eventEmitter.listeners(event) as Array<(data: unknown) => Promise | void>; - // Execute all listeners sequentially and await each one - for (const listener of listeners) { - await listener(data); + const results = await Promise.allSettled(listeners.map(async (listener) => listener(data))); + const errors = results.filter((result): result is PromiseRejectedResult => result.status === 'rejected').map((result) => result.reason); + if (errors.length === 1) { + throw errors[0]; + } + if (errors.length > 1) { + throw new AggregateError(errors, `Multiple handlers failed for event ${event}`); } } public on(event: string, listener: (rawPayload: unknown) => Promise | void) { - this.eventEmitter.on(event, (data) => { - // Call the listener and ignore any returned Promise - void listener(data); - }); + this.eventEmitter.on(event, listener); } public removeAllListeners() { @@ -81,6 +82,7 @@ class NodeEventBusImpl implements EventBus { } catch (err) { span.setStatus({ code: SpanStatusCode.ERROR }); span.recordException(err as Error); + throw err; } finally { span.end(); } @@ -129,6 +131,7 @@ class NodeEventBusImpl implements EventBus { }); console.error(`Error handling node event ${event.name} with data ${JSON.stringify(payload)}`); console.error(e as Error); + throw e; } finally { span.end(); } diff --git a/packages/cellix/mongoose-seedwork/src/mongoose-seedwork/mongo-repository.test.ts b/packages/cellix/mongoose-seedwork/src/mongoose-seedwork/mongo-repository.test.ts index 195638f87..b5136e587 100644 --- a/packages/cellix/mongoose-seedwork/src/mongoose-seedwork/mongo-repository.test.ts +++ b/packages/cellix/mongoose-seedwork/src/mongoose-seedwork/mongo-repository.test.ts @@ -1,15 +1,15 @@ +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { describeFeature, loadFeature } from '@amiceli/vitest-cucumber'; import { AggregateRoot } from '@cellix/domain-seedwork/aggregate-root'; import { CustomDomainEventImpl } from '@cellix/domain-seedwork/domain-event'; -import type { TypeConverter } from '@cellix/domain-seedwork/type-converter'; import type { EventBus } from '@cellix/domain-seedwork/event-bus'; import { NotFoundError } from '@cellix/domain-seedwork/repository'; -import { describeFeature, loadFeature } from '@amiceli/vitest-cucumber'; +import type { TypeConverter } from '@cellix/domain-seedwork/type-converter'; import type mongoose from 'mongoose'; import { expect, type Mock, vi } from 'vitest'; import type { Base } from './base.ts'; import { MongoRepositoryBase } from './mongo-repository.ts'; -import path from 'node:path'; -import { fileURLToPath } from 'node:url'; // Minimal Base (MongoType) diff --git a/packages/cellix/mongoose-seedwork/src/mongoose-seedwork/mongo-repository.ts b/packages/cellix/mongoose-seedwork/src/mongoose-seedwork/mongo-repository.ts index e43d0ce8a..3801e52bf 100644 --- a/packages/cellix/mongoose-seedwork/src/mongoose-seedwork/mongo-repository.ts +++ b/packages/cellix/mongoose-seedwork/src/mongoose-seedwork/mongo-repository.ts @@ -1,10 +1,10 @@ -import type { DomainEntityProps } from '@cellix/domain-seedwork/domain-entity'; import type { AggregateRoot } from '@cellix/domain-seedwork/aggregate-root'; -import { NotFoundError } from '@cellix/domain-seedwork/repository'; +import type { DomainEntityProps } from '@cellix/domain-seedwork/domain-entity'; +import type { CustomDomainEvent } from '@cellix/domain-seedwork/domain-event'; +import type { EventBus } from '@cellix/domain-seedwork/event-bus'; import type { Repository } from '@cellix/domain-seedwork/repository'; +import { NotFoundError } from '@cellix/domain-seedwork/repository'; import type { TypeConverter } from '@cellix/domain-seedwork/type-converter'; -import type { EventBus } from '@cellix/domain-seedwork/event-bus'; -import type { CustomDomainEvent } from '@cellix/domain-seedwork/domain-event'; import type { ClientSession, Model } from 'mongoose'; import type { Base } from './base.ts'; diff --git a/packages/cellix/mongoose-seedwork/src/mongoose-seedwork/mongo-unit-of-work.test.ts b/packages/cellix/mongoose-seedwork/src/mongoose-seedwork/mongo-unit-of-work.test.ts index 54ec80f6f..654f768b5 100644 --- a/packages/cellix/mongoose-seedwork/src/mongoose-seedwork/mongo-unit-of-work.test.ts +++ b/packages/cellix/mongoose-seedwork/src/mongoose-seedwork/mongo-unit-of-work.test.ts @@ -1,19 +1,20 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ + +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { describeFeature, loadFeature } from '@amiceli/vitest-cucumber'; import { AggregateRoot } from '@cellix/domain-seedwork/aggregate-root'; import type { DomainEntityProps } from '@cellix/domain-seedwork/domain-entity'; import { CustomDomainEventImpl } from '@cellix/domain-seedwork/domain-event'; import type { EventBus } from '@cellix/domain-seedwork/event-bus'; import type { TypeConverter } from '@cellix/domain-seedwork/type-converter'; import type { InitializedUnitOfWork } from '@cellix/domain-seedwork/unit-of-work'; -import { describeFeature, loadFeature } from '@amiceli/vitest-cucumber'; -import { expect, vi, type Mock } from 'vitest'; -import path from 'node:path'; -import { fileURLToPath } from 'node:url'; import type { ClientSession, Model } from 'mongoose'; import mongoose from 'mongoose'; +import { expect, type Mock, vi } from 'vitest'; import type { Base } from './index.ts'; -import { MongoUnitOfWork, getInitializedUnitOfWork } from './mongo-unit-of-work.ts'; import { MongoRepositoryBase } from './mongo-repository.ts'; +import { getInitializedUnitOfWork, MongoUnitOfWork } from './mongo-unit-of-work.ts'; // Type alias for test purposes to avoid linting issues diff --git a/packages/ocom-verification/verification-shared/src/scenarios/staff/staff-role-management.feature b/packages/ocom-verification/verification-shared/src/scenarios/staff/staff-role-management.feature index 5d1543efe..fe9d01065 100644 --- a/packages/ocom-verification/verification-shared/src/scenarios/staff/staff-role-management.feature +++ b/packages/ocom-verification/verification-shared/src/scenarios/staff/staff-role-management.feature @@ -174,6 +174,13 @@ Feature: Staff role management When Alice views the details of the staff role "Guarded Role" Then she should not see a delete action for the staff role + @ui-only + Scenario: Staff user with only the remove-role permission can delete a staff role + Given Alice is an authenticated staff user with only the "canRemoveRole" role permission + And a staff role named "Remove Only Role" exists + When Alice deletes the staff role "Remove Only Role" + Then the staff roles list should not include "Remove Only Role" + @skip-api Scenario: Cancelling the delete confirmation leaves the staff role intact Given Alice is an authenticated "tech admin" staff user diff --git a/packages/ocom/application-services/src/contexts/user/staff-role/delete.test.ts b/packages/ocom/application-services/src/contexts/user/staff-role/delete.test.ts index 66ba39284..a3aa69c48 100644 --- a/packages/ocom/application-services/src/contexts/user/staff-role/delete.test.ts +++ b/packages/ocom/application-services/src/contexts/user/staff-role/delete.test.ts @@ -21,7 +21,7 @@ function makeMockStaffRole() { test.for(feature, ({ Scenario, BeforeEachScenario }) => { let dataSources: DataSources; - let deleteRole: (command: { roleId: string }) => Promise; + let deleteRole: (command: { roleId: string; actorStaffUserId: string }) => Promise; let mockRepo: { getById: ReturnType; save: ReturnType; @@ -59,12 +59,12 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { }); When('I delete role "507f1f77bcf86cd799439011"', async () => { - await deleteRole({ roleId: '507f1f77bcf86cd799439011' }); + await deleteRole({ roleId: '507f1f77bcf86cd799439011', actorStaffUserId: 'actor-1' }); }); Then('the role should be marked for deletion and saved', () => { expect(mockRepo.getById).toHaveBeenCalledWith('507f1f77bcf86cd799439011'); - expect(mockRole.requestDelete).toHaveBeenCalledTimes(1); + expect(mockRole.requestDelete).toHaveBeenCalledWith('actor-1'); expect(mockRepo.save).toHaveBeenCalledWith(mockRole); }); }); @@ -76,7 +76,7 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { When('I try to delete role "507f1f77bcf86cd799439011"', async () => { try { - await deleteRole({ roleId: '507f1f77bcf86cd799439011' }); + await deleteRole({ roleId: '507f1f77bcf86cd799439011', actorStaffUserId: 'actor-1' }); } catch (error) { thrownError = error as Error; } @@ -100,7 +100,7 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { When('I try to delete role "507f1f77bcf86cd799439011"', async () => { try { - await deleteRole({ roleId: '507f1f77bcf86cd799439011' }); + await deleteRole({ roleId: '507f1f77bcf86cd799439011', actorStaffUserId: 'actor-1' }); } catch (error) { thrownError = error as Error; } diff --git a/packages/ocom/application-services/src/contexts/user/staff-role/delete.ts b/packages/ocom/application-services/src/contexts/user/staff-role/delete.ts index d4e2e2953..e25d8ccf4 100644 --- a/packages/ocom/application-services/src/contexts/user/staff-role/delete.ts +++ b/packages/ocom/application-services/src/contexts/user/staff-role/delete.ts @@ -2,13 +2,14 @@ import type { DataSources } from '@ocom/persistence'; export interface StaffRoleDeleteCommand { roleId: string; + actorStaffUserId: string; } export const deleteStaffRole = (dataSources: DataSources) => { return async (command: StaffRoleDeleteCommand): Promise => { await dataSources.domainDataSource.User.StaffRole.StaffRoleUnitOfWork.withScopedTransaction(async (repository) => { const roleToDelete = await repository.getById(command.roleId); - roleToDelete.requestDelete(); + roleToDelete.requestDelete(command.actorStaffUserId); await repository.save(roleToDelete); }); }; diff --git a/packages/ocom/application-services/src/contexts/user/staff-role/index.test.ts b/packages/ocom/application-services/src/contexts/user/staff-role/index.test.ts index 8bc821a8b..951584446 100644 --- a/packages/ocom/application-services/src/contexts/user/staff-role/index.test.ts +++ b/packages/ocom/application-services/src/contexts/user/staff-role/index.test.ts @@ -111,7 +111,7 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { }); When('I delete role "role1"', async () => { - await service.delete({ roleId: 'role1' }); + await service.delete({ roleId: 'role1', actorStaffUserId: 'actor-1' }); }); Then('it should delegate to the delete function', () => { diff --git a/packages/ocom/application-services/src/contexts/user/staff-user/assign-role.test.ts b/packages/ocom/application-services/src/contexts/user/staff-user/assign-role.test.ts index a9b6cf436..06a57da17 100644 --- a/packages/ocom/application-services/src/contexts/user/staff-user/assign-role.test.ts +++ b/packages/ocom/application-services/src/contexts/user/staff-user/assign-role.test.ts @@ -1,7 +1,7 @@ import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { describeFeature, loadFeature } from '@amiceli/vitest-cucumber'; -import type { Domain } from '@ocom/domain'; +import { Domain } from '@ocom/domain'; import type { DataSources } from '@ocom/persistence'; import { expect, vi } from 'vitest'; import { assignRole, type StaffUserAssignRoleCommand } from './assign-role.ts'; @@ -67,6 +67,7 @@ function makeDataSources(overrides: { staffRole?: Domain.Contexts.User.StaffRole.StaffRoleEntityReference | null; savedUser?: Domain.Contexts.User.StaffUser.StaffUserEntityReference; explicitUndefinedSave?: boolean; + roleUnavailableAfterSave?: boolean; }): DataSources & { _staffUserRepo: unknown; _staffRoleRepo: unknown } { const staffUser = overrides.staffUser ?? makeMockStaffUserInstance('user-123'); const { staffRole } = overrides; @@ -77,8 +78,18 @@ function makeDataSources(overrides: { save: vi.fn().mockResolvedValue(savedUser), } as unknown as Domain.Contexts.User.StaffUser.StaffUserRepository; + const getById = vi.fn(); + if (staffRole === null) { + getById.mockResolvedValue(null); + } else if (overrides.roleUnavailableAfterSave) { + const notFoundError = new Error(`StaffRole with id ${staffRole?.id} not found`); + notFoundError.name = 'NotFoundError'; + getById.mockResolvedValueOnce(staffRole).mockRejectedValueOnce(notFoundError); + } else { + getById.mockResolvedValue(staffRole); + } const staffRoleRepo = { - getById: staffRole === null ? vi.fn().mockResolvedValue(null) : vi.fn().mockResolvedValue(staffRole), + getById, } as unknown as Domain.Contexts.User.StaffRole.StaffRoleRepository; return { @@ -154,6 +165,11 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { expect(result).toBeDefined(); expect(result?.id).toBe('user-123'); }); + + And('the staff role should be validated before and after assignment', () => { + const repo = dataSources._staffRoleRepo as { getById: ReturnType }; + expect(repo.getById).toHaveBeenCalledTimes(2); + }); }); // ─── Role not found ─────────────────────────────────────────────────────── @@ -212,4 +228,34 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { expect((thrownError as Error).message).toBe('Unable to assign role to staff user'); }); }); + + Scenario('Compensates when the role is deleted during assignment', ({ Given, And, When, Then }) => { + let reassignmentSpy: ReturnType; + Given('a staff user with id "user-123" exists', () => { + staffUser = makeMockStaffUserInstance('user-123'); + }); + + And('role "role-456" is deleted after the staff user is saved', () => { + staffRole = makeMockStaffRoleRef('role-456'); + dataSources = makeDataSources({ staffUser, staffRole, roleUnavailableAfterSave: true }); + reassignmentSpy = vi.spyOn(Domain.Services.User.StaffRoleDeletedReassignmentService, 'reassignStaffUsersToDefaultRole').mockResolvedValue(undefined); + }); + + When('I call assignRole with staffUserId "user-123" and roleId "role-456"', async () => { + try { + result = await assignRole(dataSources)(command); + } catch (error) { + thrownError = error; + } + }); + + Then('staff users assigned to role "role-456" should be reassigned using enterprise app role "role-role-456"', () => { + expect(reassignmentSpy).toHaveBeenCalledWith('role-456', 'role-role-456', 'actor-1', dataSources.domainDataSource); + }); + + And('it should throw an error with message containing "no longer available"', () => { + expect((thrownError as Error).name).toBe('NotFoundError'); + expect((thrownError as Error).message).toContain('no longer available'); + }); + }); }); diff --git a/packages/ocom/application-services/src/contexts/user/staff-user/assign-role.ts b/packages/ocom/application-services/src/contexts/user/staff-user/assign-role.ts index 0961262fa..6a8cbee11 100644 --- a/packages/ocom/application-services/src/contexts/user/staff-user/assign-role.ts +++ b/packages/ocom/application-services/src/contexts/user/staff-user/assign-role.ts @@ -1,4 +1,4 @@ -import type { Domain } from '@ocom/domain'; +import { Domain } from '@ocom/domain'; import type { DataSources } from '@ocom/persistence'; export interface StaffUserAssignRoleCommand { @@ -7,25 +7,24 @@ export interface StaffUserAssignRoleCommand { actorStaffUserId: string; } +const isNotFoundError = (error: unknown): boolean => error instanceof Error && (error.name === 'NotFoundError' || error.message.toLowerCase().includes('not found')); + export const assignRole = (dataSources: DataSources) => { return async (command: StaffUserAssignRoleCommand): Promise => { let result: Domain.Contexts.User.StaffUser.StaffUserEntityReference | undefined; + let role: Domain.Contexts.User.StaffRole.StaffRoleEntityReference | undefined; - await dataSources.domainDataSource.User.StaffUser.StaffUserUnitOfWork.withScopedTransaction(async (staffUserRepo) => { - const staffUser = await staffUserRepo.get(command.staffUserId); + await dataSources.domainDataSource.User.StaffRole.StaffRoleUnitOfWork.withScopedTransaction(async (staffRoleRepo) => { + role = await staffRoleRepo.getById(command.roleId); + }); - let role!: Domain.Contexts.User.StaffRole.StaffRoleEntityReference; - await dataSources.domainDataSource.User.StaffRole.StaffRoleUnitOfWork.withScopedTransaction(async (staffRoleRepo) => { - const foundRole = await staffRoleRepo.getById(command.roleId); - if (!foundRole) { - return; - } - role = foundRole; - }); + const roleToAssign = role; + if (!roleToAssign) { + throw new Error(`StaffRole with id ${command.roleId} not found`); + } - if (!role) { - throw new Error(`StaffRole with id ${command.roleId} not found`); - } + await dataSources.domainDataSource.User.StaffUser.StaffUserUnitOfWork.withScopedTransaction(async (staffUserRepo) => { + const staffUser = await staffUserRepo.get(command.staffUserId); // Build a descriptive activity message including role name, target user and actor (fallback to IDs when names unavailable) let actorDisplayName = command.actorStaffUserId; @@ -38,9 +37,9 @@ export const assignRole = (dataSources: DataSources) => { throw error; } } - const roleName = role.roleName ?? command.roleId; + const roleName = roleToAssign.roleName ?? command.roleId; const description = `${roleName} assigned by ${actorDisplayName}`; - staffUser.requestRoleAssignment(role, description, command.actorStaffUserId); + staffUser.requestRoleAssignment(roleToAssign, description, command.actorStaffUserId); result = await staffUserRepo.save(staffUser); }); @@ -48,6 +47,24 @@ export const assignRole = (dataSources: DataSources) => { throw new Error('Unable to assign role to staff user'); } + try { + let roleStillExists = false; + await dataSources.domainDataSource.User.StaffRole.StaffRoleUnitOfWork.withScopedTransaction(async (staffRoleRepo) => { + roleStillExists = Boolean(await staffRoleRepo.getById(command.roleId)); + }); + if (!roleStillExists) { + throw new Error(`StaffRole with id ${command.roleId} not found`); + } + } catch (error) { + if (!isNotFoundError(error)) { + throw error; + } + await Domain.Services.User.StaffRoleDeletedReassignmentService.reassignStaffUsersToDefaultRole(command.roleId, roleToAssign.enterpriseAppRole, command.actorStaffUserId, dataSources.domainDataSource); + const unavailableRoleError = new Error(`StaffRole with id ${command.roleId} is no longer available for assignment`); + unavailableRoleError.name = 'NotFoundError'; + throw unavailableRoleError; + } + return result; }; }; diff --git a/packages/ocom/application-services/src/contexts/user/staff-user/features/assign-role.feature b/packages/ocom/application-services/src/contexts/user/staff-user/features/assign-role.feature index 0a105591d..7f68757a4 100644 --- a/packages/ocom/application-services/src/contexts/user/staff-user/features/assign-role.feature +++ b/packages/ocom/application-services/src/contexts/user/staff-user/features/assign-role.feature @@ -6,6 +6,7 @@ Feature: Assign role to staff user When I call assignRole with staffUserId "user-123" and roleId "role-456" Then the staff user should be saved with the role assigned And the result should be the updated staff user + And the staff role should be validated before and after assignment Scenario: Throws an error when the staff role does not exist Given a staff user with id "user-123" exists @@ -19,3 +20,10 @@ Feature: Assign role to staff user And saving the staff user returns undefined When I call assignRole with staffUserId "user-123" and roleId "role-456" Then it should throw an error with message "Unable to assign role to staff user" + + Scenario: Compensates when the role is deleted during assignment + Given a staff user with id "user-123" exists + And role "role-456" is deleted after the staff user is saved + When I call assignRole with staffUserId "user-123" and roleId "role-456" + Then staff users assigned to role "role-456" should be reassigned using enterprise app role "role-role-456" + And it should throw an error with message containing "no longer available" diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.test.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.test.ts index 16c5c6816..6cee63002 100644 --- a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.test.ts +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.test.ts @@ -205,7 +205,7 @@ test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { deletedRole = new StaffRole(makeBaseProps({ isDefault: false, enterpriseAppRole: 'Staff.CaseManager' }), passport); }); When('I call requestDelete', () => { - deletedRole.requestDelete(); + deletedRole.requestDelete('actor-1'); }); Then('the staff role should be marked as deleted', () => { expect(deletedRole.isDeleted).toBe(true); @@ -216,6 +216,7 @@ test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { expect(event).toBeInstanceOf(StaffRoleDeletedEvent); expect(event?.payload.deletedRoleId).toBe('role-1'); expect(event?.payload.enterpriseAppRole).toBe('Staff.CaseManager'); + expect(event?.payload.actorStaffUserId).toBe('actor-1'); }); }); @@ -228,7 +229,7 @@ test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { }); When('I try to call requestDelete', () => { deletingRoleWithoutPermission = () => { - deletedRole.requestDelete(); + deletedRole.requestDelete('actor-1'); }; }); Then('a PermissionError should be thrown', () => { @@ -250,7 +251,7 @@ test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { }); When('I try to call requestDelete', () => { deletingDefaultRole = () => { - defaultRole.requestDelete(); + defaultRole.requestDelete('actor-1'); }; }); Then('a PermissionError should be thrown', () => { @@ -268,11 +269,11 @@ test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { Given('a StaffRole aggregate that is already deleted, with permission to remove staff roles', () => { passport = makePassport(false, false, true); deletedRole = new StaffRole(makeBaseProps({ isDefault: false }), passport); - deletedRole.requestDelete(); + deletedRole.requestDelete('actor-1'); deletedRole.clearIntegrationEvents(); }); When('I call requestDelete again', () => { - deletedRole.requestDelete(); + deletedRole.requestDelete('actor-2'); }); Then('no additional StaffRoleDeletedEvent should be emitted', () => { expect(deletedRole.isDeleted).toBe(true); diff --git a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.ts b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.ts index 098ce000e..bdd892ae7 100644 --- a/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.ts +++ b/packages/ocom/domain/src/domain/contexts/user/staff-role/staff-role.ts @@ -133,7 +133,7 @@ export class StaffRole extends AggregateRoot extends AggregateRoot(StaffRoleDeletedEvent, { deletedRoleId: this.props.id, enterpriseAppRole: this.props.enterpriseAppRole, + actorStaffUserId, }); } diff --git a/packages/ocom/domain/src/domain/events/types/staff-role-deleted.ts b/packages/ocom/domain/src/domain/events/types/staff-role-deleted.ts index ccb4e5b65..dcb514346 100644 --- a/packages/ocom/domain/src/domain/events/types/staff-role-deleted.ts +++ b/packages/ocom/domain/src/domain/events/types/staff-role-deleted.ts @@ -2,6 +2,7 @@ import { CustomDomainEventImpl } from '@cellix/domain-seedwork/domain-event'; export interface StaffRoleDeletedProps { deletedRoleId: string; + actorStaffUserId: string; /** * Enterprise app role of the deleted staff role. Carried on the payload * because the staff role document is hard-deleted when the deletion diff --git a/packages/ocom/domain/src/domain/services/user/staff-role-deleted-reassignment.service.test.ts b/packages/ocom/domain/src/domain/services/user/staff-role-deleted-reassignment.service.test.ts index 8c6da6af7..36c04147a 100644 --- a/packages/ocom/domain/src/domain/services/user/staff-role-deleted-reassignment.service.test.ts +++ b/packages/ocom/domain/src/domain/services/user/staff-role-deleted-reassignment.service.test.ts @@ -110,13 +110,13 @@ test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { assignedStaffUsers = [makeMockStaffUser('staff-user-1', 'deleted-role-1'), makeMockStaffUser('staff-user-2', 'deleted-role-1')]; }); When('I call reassignStaffUsersToDefaultRole for role "deleted-role-1" with enterpriseAppRole "Staff.CaseManager"', async () => { - await service.reassignStaffUsersToDefaultRole('deleted-role-1', 'Staff.CaseManager', mockDomainDataSource); + await service.reassignStaffUsersToDefaultRole('deleted-role-1', 'Staff.CaseManager', 'actor-1', mockDomainDataSource); }); Then('each assigned staff user should be reassigned to the default role "default-role-1"', () => { expect(mockStaffUserRepo.getAllAssignedToRole).toHaveBeenCalledWith('deleted-role-1'); for (const staffUser of assignedStaffUsers) { expect(staffUser.requestRoleAssignment).toHaveBeenCalledTimes(1); - expect(staffUser.requestRoleAssignment).toHaveBeenCalledWith(mockDefaultRole, expect.stringContaining('Default Case Manager'), staffUser.id); + expect(staffUser.requestRoleAssignment).toHaveBeenCalledWith(mockDefaultRole, expect.stringContaining('Default Case Manager'), 'actor-1'); } expect(capturedPassport).toBeDefined(); }); @@ -132,7 +132,7 @@ test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { assignedStaffUsers = [makeMockStaffUser('staff-user-1', 'default-role-1')]; }); When('I call reassignStaffUsersToDefaultRole for role "deleted-role-1" with enterpriseAppRole "Staff.CaseManager"', async () => { - await service.reassignStaffUsersToDefaultRole('deleted-role-1', 'Staff.CaseManager', mockDomainDataSource); + await service.reassignStaffUsersToDefaultRole('deleted-role-1', 'Staff.CaseManager', 'actor-1', mockDomainDataSource); }); Then('that staff user should not be reassigned again', () => { expect(assignedStaffUsers[0]?.requestRoleAssignment).not.toHaveBeenCalled(); @@ -147,7 +147,7 @@ test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { assignedStaffUsers = []; }); When('I call reassignStaffUsersToDefaultRole for role "deleted-role-1" with enterpriseAppRole "Staff.CaseManager"', async () => { - await service.reassignStaffUsersToDefaultRole('deleted-role-1', 'Staff.CaseManager', mockDomainDataSource); + await service.reassignStaffUsersToDefaultRole('deleted-role-1', 'Staff.CaseManager', 'actor-1', mockDomainDataSource); }); Then('no staff user should be saved', () => { expect(mockStaffUserRepo.save).not.toHaveBeenCalled(); @@ -160,7 +160,7 @@ test.for(feature, ({ Scenario, Background, BeforeEachScenario }) => { }); When('I try to call reassignStaffUsersToDefaultRole for role "deleted-role-1" with enterpriseAppRole "Staff.Unmatched"', async () => { try { - await service.reassignStaffUsersToDefaultRole('deleted-role-1', 'Staff.Unmatched', mockDomainDataSource); + await service.reassignStaffUsersToDefaultRole('deleted-role-1', 'Staff.Unmatched', 'actor-1', mockDomainDataSource); } catch (error) { thrownError = error as Error; } diff --git a/packages/ocom/domain/src/domain/services/user/staff-role-deleted-reassignment.service.ts b/packages/ocom/domain/src/domain/services/user/staff-role-deleted-reassignment.service.ts index 1b1923050..ffbdd15b1 100644 --- a/packages/ocom/domain/src/domain/services/user/staff-role-deleted-reassignment.service.ts +++ b/packages/ocom/domain/src/domain/services/user/staff-role-deleted-reassignment.service.ts @@ -14,7 +14,7 @@ export class StaffRoleDeletedReassignmentService { * enterpriseAppRole — the failure is logged and rethrown so the event is * observed as a processing failure instead of silently stranding users. */ - async reassignStaffUsersToDefaultRole(deletedRoleId: string, enterpriseAppRole: string, domainDataSource: DomainDataSource): Promise { + async reassignStaffUsersToDefaultRole(deletedRoleId: string, enterpriseAppRole: string, actorStaffUserId: string, domainDataSource: DomainDataSource): Promise { let defaultRole: StaffRole.StaffRoleEntityReference | null = null; try { await domainDataSource.User.StaffRole.StaffRoleUnitOfWork.withScopedTransaction(async (repo) => { @@ -40,7 +40,7 @@ export class StaffRoleDeletedReassignmentService { if (staffUser.role?.id === matchingDefaultRole.id) { continue; } - staffUser.requestRoleAssignment(matchingDefaultRole, `Reassigned to default role ${matchingDefaultRole.roleName} after previous role was deleted`, staffUser.id); + staffUser.requestRoleAssignment(matchingDefaultRole, `Reassigned to default role ${matchingDefaultRole.roleName} after previous role was deleted`, actorStaffUserId); await repo.save(staffUser); } }); diff --git a/packages/ocom/event-handler/src/handlers/integration/staff-role-deleted--reassign-staff-users.ts b/packages/ocom/event-handler/src/handlers/integration/staff-role-deleted--reassign-staff-users.ts index 86daecb41..17a94a5bc 100644 --- a/packages/ocom/event-handler/src/handlers/integration/staff-role-deleted--reassign-staff-users.ts +++ b/packages/ocom/event-handler/src/handlers/integration/staff-role-deleted--reassign-staff-users.ts @@ -3,7 +3,7 @@ import { Domain, type DomainDataSource } from '@ocom/domain'; const { EventBusInstance, StaffRoleDeletedEvent } = Domain.Events; export default (domainDataSource: DomainDataSource) => { EventBusInstance.register(StaffRoleDeletedEvent, async (payload) => { - const { deletedRoleId, enterpriseAppRole } = payload; - return await Domain.Services.User.StaffRoleDeletedReassignmentService.reassignStaffUsersToDefaultRole(deletedRoleId, enterpriseAppRole, domainDataSource); + const { deletedRoleId, enterpriseAppRole, actorStaffUserId } = payload; + return await Domain.Services.User.StaffRoleDeletedReassignmentService.reassignStaffUsersToDefaultRole(deletedRoleId, enterpriseAppRole, actorStaffUserId, domainDataSource); }); }; diff --git a/packages/ocom/graphql/src/schema/types/features/staff-role.resolvers.feature b/packages/ocom/graphql/src/schema/types/features/staff-role.resolvers.feature index 0c7fec2f2..a8a642453 100644 --- a/packages/ocom/graphql/src/schema/types/features/staff-role.resolvers.feature +++ b/packages/ocom/graphql/src/schema/types/features/staff-role.resolvers.feature @@ -3,7 +3,7 @@ Feature: StaffRole resolvers Scenario: Deleting a staff role successfully Given a staff user with a verified JWT When the staffRoleDelete mutation is executed for role "607f1f77bcf86cd799439099" - Then it should call User.StaffRole.delete with the role id + Then it should call User.StaffRole.delete with the role id and initiating staff user id And it should return a success status Scenario: Unauthorized staff role deletion diff --git a/packages/ocom/graphql/src/schema/types/staff-role.command-mapper.ts b/packages/ocom/graphql/src/schema/types/staff-role.command-mapper.ts index 04d67fb33..189001699 100644 --- a/packages/ocom/graphql/src/schema/types/staff-role.command-mapper.ts +++ b/packages/ocom/graphql/src/schema/types/staff-role.command-mapper.ts @@ -72,8 +72,9 @@ export function buildStaffRoleUpdateCommand(input: NonNullable): StaffRoleDeleteCommand { +export function buildStaffRoleDeleteCommand(input: NonNullable, actorStaffUserId: string): StaffRoleDeleteCommand { return { roleId: String(input.id), + actorStaffUserId, }; } diff --git a/packages/ocom/graphql/src/schema/types/staff-role.resolvers.test.ts b/packages/ocom/graphql/src/schema/types/staff-role.resolvers.test.ts index 6ff814c2d..c4e1fe797 100644 --- a/packages/ocom/graphql/src/schema/types/staff-role.resolvers.test.ts +++ b/packages/ocom/graphql/src/schema/types/staff-role.resolvers.test.ts @@ -20,6 +20,9 @@ function makeMockGraphContext(verified: boolean): GraphContext { StaffRole: { delete: vi.fn(), }, + StaffUser: { + queryByExternalId: vi.fn().mockResolvedValue({ id: 'actor-1' }), + }, }, ...(verified ? { @@ -59,9 +62,11 @@ test.for(feature, ({ Scenario, BeforeEachScenario }) => { await executeDelete('607f1f77bcf86cd799439099'); }); - Then('it should call User.StaffRole.delete with the role id', () => { + Then('it should call User.StaffRole.delete with the role id and initiating staff user id', () => { + expect(context.applicationServices.User.StaffUser.queryByExternalId).toHaveBeenCalledWith({ externalId: 'staff-user-sub' }); expect(context.applicationServices.User.StaffRole.delete).toHaveBeenCalledWith({ roleId: '607f1f77bcf86cd799439099', + actorStaffUserId: 'actor-1', }); }); diff --git a/packages/ocom/graphql/src/schema/types/staff-role.resolvers.ts b/packages/ocom/graphql/src/schema/types/staff-role.resolvers.ts index 818e9c5d9..ce1ee5f08 100644 --- a/packages/ocom/graphql/src/schema/types/staff-role.resolvers.ts +++ b/packages/ocom/graphql/src/schema/types/staff-role.resolvers.ts @@ -63,7 +63,11 @@ const staffRole: Resolvers = { return { status: { success: false, errorMessage: 'Unauthorized' } }; } try { - const command = buildStaffRoleDeleteCommand(args.input); + const actorStaffUser = await context.applicationServices.User.StaffUser.queryByExternalId({ externalId: jwt.sub }); + if (!actorStaffUser) { + throw new Error('Current staff user not found'); + } + const command = buildStaffRoleDeleteCommand(args.input, String(actorStaffUser.id)); await context.applicationServices.User.StaffRole.delete(command); return { status: { success: true } }; } catch (error) { diff --git a/packages/ocom/persistence/src/datasources/domain/user/staff-user/staff-user.domain-adapter.test.ts b/packages/ocom/persistence/src/datasources/domain/user/staff-user/staff-user.domain-adapter.test.ts index a71c342eb..ab2beba7f 100644 --- a/packages/ocom/persistence/src/datasources/domain/user/staff-user/staff-user.domain-adapter.test.ts +++ b/packages/ocom/persistence/src/datasources/domain/user/staff-user/staff-user.domain-adapter.test.ts @@ -2,13 +2,12 @@ import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { describeFeature, loadFeature } from '@amiceli/vitest-cucumber'; import { MongooseSeedwork } from '@cellix/mongoose-seedwork'; - +import type { StaffRole } from '@ocom/data-sources-mongoose-models/role/staff-role'; +import type { StaffUser } from '@ocom/data-sources-mongoose-models/user/staff-user'; import type { Domain } from '@ocom/domain'; import { expect, vi } from 'vitest'; import { StaffRoleDomainAdapter } from '../staff-role/staff-role.domain-adapter.ts'; import { StaffUserDomainAdapter } from './staff-user.domain-adapter.ts'; -import type { StaffRole } from '@ocom/data-sources-mongoose-models/role/staff-role'; -import type { StaffUser } from '@ocom/data-sources-mongoose-models/user/staff-user'; const test = { for: describeFeature }; const __dirname = path.dirname(fileURLToPath(import.meta.url)); diff --git a/packages/ocom/ui-staff-route-user-management/src/components/staff-role-create.test.tsx b/packages/ocom/ui-staff-route-user-management/src/components/staff-role-create.test.tsx index 59189ae55..2669e5386 100644 --- a/packages/ocom/ui-staff-route-user-management/src/components/staff-role-create.test.tsx +++ b/packages/ocom/ui-staff-route-user-management/src/components/staff-role-create.test.tsx @@ -84,6 +84,14 @@ describe('StaffRoleCreate', () => { const rendered = renderComponent({ mode: 'edit' }); expect(rendered.textContent).toContain('Edit Staff Role'); }); + + it('renders a details title and hides editing controls in read-only mode', () => { + const rendered = renderComponent({ mode: 'edit', editable: false, showDelete: true, onDelete: vi.fn() }); + expect(rendered.textContent).toContain('Staff Role Details'); + expect(findButtonByText(rendered, 'Update Role')).toBeUndefined(); + expect(findButtonByText(rendered, 'Delete Role')).toBeDefined(); + expect(Array.from(rendered.querySelectorAll('input')).every((input) => input.disabled)).toBe(true); + }); }); describe('delete action visibility', () => { diff --git a/packages/ocom/ui-staff-route-user-management/src/components/staff-role-create.tsx b/packages/ocom/ui-staff-route-user-management/src/components/staff-role-create.tsx index be25181af..2574ec5f5 100644 --- a/packages/ocom/ui-staff-route-user-management/src/components/staff-role-create.tsx +++ b/packages/ocom/ui-staff-route-user-management/src/components/staff-role-create.tsx @@ -41,6 +41,7 @@ interface StaffRoleCreateProps { showDelete?: boolean; onDelete?: () => void; deleting?: boolean; + editable?: boolean; } type PermissionFieldKey = keyof Omit; @@ -146,7 +147,19 @@ const DEFAULT_VALUES: StaffRoleFormValues = { canSendQueueMessages: false, }; -export const StaffRoleCreate: React.FC = ({ onSubmit, onCancel, loading, availableEnterpriseAppRoles, showTechAdminPermissions, initialValues, mode = 'create', showDelete, onDelete, deleting }) => { +export const StaffRoleCreate: React.FC = ({ + onSubmit, + onCancel, + loading, + availableEnterpriseAppRoles, + showTechAdminPermissions, + initialValues, + mode = 'create', + showDelete, + onDelete, + deleting, + editable = true, +}) => { const [form] = Form.useForm(); const defaultValues: StaffRoleFormValues = { @@ -180,7 +193,7 @@ export const StaffRoleCreate: React.FC = ({ onSubmit, onCa level={4} style={{ margin: 0 }} > - {isEdit ? 'Edit Staff Role' : 'Create Staff Role'} + {isEdit ? (editable ? 'Edit Staff Role' : 'Staff Role Details') : 'Create Staff Role'} {isEdit && showDelete && onDelete && ( = ({ onSubmit, onCa label="Role Name" rules={[{ required: true, message: 'Role name is required' }]} > - + = ({ onSubmit, onCa rules={[{ required: true, message: 'Enterprise app role is required' }]} >