From f4005135b4d688149cd39ebaf2aff58695e0fed7 Mon Sep 17 00:00:00 2001 From: Ruben van der Linde Date: Sun, 9 Aug 2026 16:28:15 +0200 Subject: [PATCH 1/2] fix(gates): one settings home, four dangling refs, two mistyped anchors, three tracked build artefacts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Four gates, thirteen findings, all real. Measured with hydra-gates 48c88ba1e0d049f8f38538c33e790d3e603c55d0. gate-63 settings-surface (2 + 1 WARN) -> PASS The app already registers a Nextcloud admin section (`lib/Settings/SoftwareCatalogAdmin.php`, wired in appinfo/info.xml) that renders `SoftwareCatalogSettings.vue` through `src/settings.js`. The manifest ALSO declared a `type: "settings"` page rendering the same component, lifted into the gear foldout by `menu-layout.json` — so the navigation read "Settings > Settings" and the app had two homes for one concern, one of them authorized only by whatever the SPA remembered to check. ADR-079 D1/D4: the in-app page and its menu entry are removed; `/settings/admin/softwarecatalog` is the single home, and CnAppNav's admin-gated "Admin settings" link out (`data-testid=cn-nav-admin-settings`, present in the pinned nc-vue) is how you get there. The three Playwright tests that drove `#/settings` are retargeted at `/settings/admin/softwarecatalog`. They assert the same three things about the same component; only the door moved. They were NOT deleted — deleting the tests would have removed the only proof this surface still renders. gate-54 relation-dialect (5 -> 1) `element.properties`, `view.properties`, `model.properties` and `relation.properties` all declare `$ref: "#/components/schemas/property"`. There is no `property` schema in the register; the slug is `property-definition`. Four dangling nested-object references, now resolved. gate-46 spec-anchor-existence (4) -> PASS - `#requirement-modulversie-...` (x2) was a typo for `#requirement-moduleversie-records-sbom-import-provenance`, which exists. - `src/utils/suiteWizard.js::mapApplicationOptions` pointed at a requirement that does not exist. The scenario that actually governs it — "The applications step only offers modules that already exist" — sits under "The wizard SHALL guide suite creation...", so the tag now names that. - `SbomParserService::parseSpdx()` pointed at `#notes`, which did not exist. SPDX 2.x parsing is live (called from SbomImportService) and unit-tested but has no requirement, so the spec gains a Notes section describing it — and says plainly that promoting it to a Requirement means writing the Scenarios and the Playwright test that assert them. gate-51 schema-property-titles (2) -> PASS `sbomComponent.hashes[].alg` and `.value` had a title but no description. gate-29 gitignore-then-commit (4) -> PASS `.phpunit.cache/test-results` and `.phpunit.result.cache` are PHPUnit build artefacts, correctly ignored and wrongly tracked — untracked with `git rm --cached`. `data/GEMMA release.xml` is a 13 MB AMEF fixture that test-setup.sh reads, sitting inside the ignored `/data/` runtime directory; it moves to `tests/fixtures/amef/` where fixtures live, and test-setup.sh follows it. Can-fail proof: reverting the six changed source files to origin/development and re-running the suite puts every count back exactly — gate-46 4, gate-51 2, gate-54 5, gate-63 2. check:manifest Ajv validation PASS (0 errors). vitest 215/215. All three touched JSON documents parse. --- .phpunit.cache/test-results | 1 - .phpunit.result.cache | 1 - lib/Service/SbomImportService.php | 4 +- lib/Settings/softwarecatalogus_register.json | 14 +++-- openspec/specs/sbom-import/spec.md | 20 +++++++ src/manifest.json | 28 --------- src/menu-layout.json | 4 +- src/utils/suiteWizard.js | 2 +- test-setup.sh | 2 +- tests/e2e/manifest-pages.spec.ts | 58 ++++++++++++------- .../fixtures/amef}/GEMMA release.xml | 0 11 files changed, 71 insertions(+), 63 deletions(-) delete mode 100644 .phpunit.cache/test-results delete mode 100644 .phpunit.result.cache rename {data => tests/fixtures/amef}/GEMMA release.xml (100%) diff --git a/.phpunit.cache/test-results b/.phpunit.cache/test-results deleted file mode 100644 index 0a9ba9a7..00000000 --- a/.phpunit.cache/test-results +++ /dev/null @@ -1 +0,0 @@ -{"version":2,"defects":{"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerTest::testHandleOrganizationCreatedEvent":1,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerTest::testHandleContactCreatedEvent":1,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerTest::testHandleGebruikerCreatedEvent":1,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerTest::testHandleContactUpdatedEvent":1,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerTest::testHandleGebruikerUpdatedEvent":1,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerTest::testHandleContactDeletedEvent":1,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerTest::testHandleGebruikerDeletedEvent":1,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerTest::testHandleGebruikerLockedEvent":1,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerTest::testHandleGebruikerUnlockedEvent":1,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerTest::testHandleContactRevertedEvent":1,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerTest::testHandleGebruikerRevertedEvent":1,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerTest::testHandleEventWithNullObject":8,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerTest::testExceptionHandlingDuringEventProcessing":1,"OCA\\SoftwareCatalog\\Tests\\Unit\\OrganisationUserWorkflowTest::testCompleteOrganisationUserWorkflow":1,"OCA\\SoftwareCatalog\\Tests\\Unit\\OrganisationUserWorkflowTest::testWorkflowWithGemeenteOrganisation":1,"OCA\\SoftwareCatalog\\Tests\\Unit\\OrganisationUserWorkflowTest::testWorkflowWithSamenwerkingOrganisation":1,"OCA\\SoftwareCatalog\\Tests\\Unit\\OrganisationUserWorkflowTest::testWorkflowWithCommunityOrganisation":1,"OCA\\SoftwareCatalog\\Tests\\Unit\\OrganisationUserWorkflowTest::testConvertContactpersoonWhenUserAlreadyExists":1,"OCA\\SoftwareCatalog\\Tests\\Unit\\OrganisationUserWorkflowTest::testPasswordChangeWithInvalidUser":1,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ContactPersonHandlerTest::testGetRoleGroupByOrganizationType":1,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ContactPersonHandlerTest::testAddUserToGroupWithCheck":1,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\EmailServiceTest::testSendOrganizationWelcomeEmailSuccess":8,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\EmailServiceTest::testSendOrganizationWelcomeEmailWithoutEmail":8,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\EmailServiceTest::testSendGebruikerWelcomeEmailSuccess":8,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\EmailServiceTest::testSendContactWelcomeEmailSuccess":8,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\EmailServiceTest::testSendEmailFailure":8,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\EmailServiceTest::testSendEmailException":8,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\EmailServiceTest::testGetSenderEmail":8,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\EmailServiceTest::testGetSenderName":8,"OCA\\SoftwareCatalog\\Tests\\Integration\\KoppelingenGebruikIntegrationTest::testGetKoppelingenGebruikForProductUuid":8,"OCA\\SoftwareCatalog\\Tests\\Integration\\KoppelingenGebruikIntegrationTest::testGetKoppelingenGebruikForModuleUuid":8,"OCA\\SoftwareCatalog\\Tests\\Integration\\KoppelingenGebruikIntegrationTest::testGetKoppelingenGebruikForOrganisationUuid":8,"OCA\\SoftwareCatalog\\Tests\\Integration\\KoppelingenGebruikIntegrationTest::testAmbtenaarAccessToAllOrganisations":8,"OCA\\SoftwareCatalog\\Tests\\Integration\\KoppelingenGebruikIntegrationTest::testPaginationParameters":8,"OCA\\SoftwareCatalog\\Tests\\Integration\\KoppelingenGebruikIntegrationTest::testResponseFormatConsistency":8,"OCA\\SoftwareCatalog\\Tests\\Integration\\KoppelingenGebruikIntegrationTest::testInvalidUuidReturnsEmptyResults":8,"OCA\\SoftwareCatalog\\Tests\\Integration\\KoppelingenGebruikIntegrationTest::testOrganisationOwnerAccessToOwnedProductUsage":8,"OCA\\SoftwareCatalog\\Tests\\Integration\\KoppelingenGebruikIntegrationTest::testThreeOrganisationAccessControlMatrix":8,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerTest::testHandleEventWithUnmatchedSchema":1,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\UserProfileUpdatedEventListenerDecompositionTest::testBuildContactPatchMapsChangedFields":1,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\UserProfileUpdatedEventListenerDecompositionTest::testBuildContactPatchCoercesNullToEmptyString":1,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\UserProfileUpdatedEventListenerDecompositionTest::testBuildContactPatchBackfillsUsername":1,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\UserProfileUpdatedEventListenerDecompositionTest::testBuildContactPatchEmptyWhenNothingToChange":1},"times":{"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerTest::testHandleOrganizationCreatedEvent":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerTest::testHandleContactCreatedEvent":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerTest::testHandleGebruikerCreatedEvent":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerTest::testHandleContactUpdatedEvent":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerTest::testHandleGebruikerUpdatedEvent":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerTest::testHandleContactDeletedEvent":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerTest::testHandleGebruikerDeletedEvent":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerTest::testHandleGebruikerLockedEvent":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerTest::testHandleGebruikerUnlockedEvent":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerTest::testHandleContactRevertedEvent":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerTest::testHandleGebruikerRevertedEvent":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerTest::testHandleEventWithNullObject":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerTest::testExceptionHandlingDuringEventProcessing":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerTest::testHandleEventWithUnmatchedSchema":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\OrganisationUserWorkflowTest::testCompleteOrganisationUserWorkflow":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\OrganisationUserWorkflowTest::testWorkflowWithGemeenteOrganisation":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\OrganisationUserWorkflowTest::testWorkflowWithSamenwerkingOrganisation":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\OrganisationUserWorkflowTest::testWorkflowWithCommunityOrganisation":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\OrganisationUserWorkflowTest::testConvertContactpersoonWhenUserAlreadyExists":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\OrganisationUserWorkflowTest::testPasswordChangeWithInvalidUser":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ContactPersonHandlerTest::testGetRoleGroupByOrganizationType":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ContactPersonHandlerTest::testAddUserToGroupWithCheck":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Controller\\ContactpersonenControllerDecompositionTest::testValidateConvertToUserPermissionReturns401WhenAnonymous":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Controller\\ContactpersonenControllerDecompositionTest::testValidateConvertToUserPermissionReturns403WhenNeitherAdminNorOrgAdmin":0.015,"OCA\\SoftwareCatalog\\Tests\\Unit\\Controller\\ContactpersonenControllerDecompositionTest::testValidateConvertToUserPermissionPassesForAdmin":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Controller\\ContactpersonenControllerDecompositionTest::testValidateConvertToUserPermissionPassesForOrgAdmin":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Controller\\ContactpersonenControllerDecompositionTest::testNormaliseContactDataCoercesNonStringFieldsAndNullsOrgUuids":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Controller\\ContactpersonenControllerDecompositionTest::testNormaliseContactDataLeavesNonStringOrgUntouched":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Controller\\ContactpersonenControllerDecompositionTest::testBuildEmptyMeResponseShape":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Controller\\ContactpersonenControllerDecompositionTest::testProjectCatalogGroupsKeepsOnlyCatalogGroups":0.002,"OCA\\SoftwareCatalog\\Tests\\Unit\\Controller\\ContactpersonenControllerUpdateUserGroupsTest::testCrossTenantUpdateDenied":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Controller\\ContactpersonenControllerUpdateUserGroupsTest::testSameTenantUpdateAllowed":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Controller\\ContactpersonenControllerUpdateUserGroupsTest::testFullAdminBypassesTenantCheck":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Controller\\GebruikControllerDecompositionTest::testAdminBypassesAanbodScope":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Controller\\GebruikControllerDecompositionTest::testAanbodWithoutApplicatiesReturnsNull":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Controller\\GebruikControllerDecompositionTest::testAanbodWithApplicatiesInjectsModuleFilter":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Controller\\GebruikControllerDecompositionTest::testAanbodWithDisallowedModuleReturnsNull":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Controller\\SettingsControllerDecompositionTest::testErrorResponseReturnsStatus500AndCanonicalShape":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Controller\\SettingsControllerDecompositionTest::testErrorResponseIncludesRedactedParamsForMutatingEndpoints":0.003,"OCA\\SoftwareCatalog\\Tests\\Unit\\Controller\\ViewControllerDecompositionTest::testDetermineListStatusCode":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Controller\\ViewControllerDecompositionTest::testDetermineViewStatusCode":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Controller\\ViewControllerDecompositionTest::testBuildListErrorPayloadIncludesExceptionMessage":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\ModuleComplianceSubscriberDecompositionTest::testExtractObjectFromUnsupportedEventReturnsNull":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\OpenRegisterEventsDebugListenerDecompositionTest::testExtractEventDataReturnsUnknownForUnknownEvent":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\OpenRegisterEventsDebugListenerDecompositionTest::testPerFamilyExtractorsReturnNullForUnknownEvent":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerDecompositionTest::testResolveCatalogSchemaIdsCastsAndPreservesNull":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerDecompositionTest::testResolveCatalogSchemaIdsTreatsNullAsNull":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerDecompositionTest::testMatchesSchemaSemantics":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerDecompositionTest::testMatchesSchemaZeroEdgeCase":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerDecompositionTest::testRunOrganizationSyncDispatchesAndLogsSuccess":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerDecompositionTest::testRunOrganizationSyncCatchesAndLogsErrors":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\SoftwareCatalogEventListenerDecompositionTest::testIsActiveStatusRecognisesDutchAndEnglish":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\UserProfileUpdatedEventListenerDecompositionTest::testBuildContactPatchMapsChangedFields":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\UserProfileUpdatedEventListenerDecompositionTest::testBuildContactPatchCoercesNullToEmptyString":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\UserProfileUpdatedEventListenerDecompositionTest::testBuildContactPatchBackfillsUsername":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\EventListener\\UserProfileUpdatedEventListenerDecompositionTest::testBuildContactPatchEmptyWhenNothingToChange":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\AanbodServiceDecompositionTest::testResolvePartyIdFromTuple":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\AanbodServiceDecompositionTest::testResolvePartyIdFromString":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\AanbodServiceDecompositionTest::testResolvePartyIdNullForUnsupportedShapes":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\AangebodenGebruikServiceDecompositionTest::testResolveReturnsTupleWhenConfigComplete":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\AangebodenGebruikServiceDecompositionTest::testResolvePicksKoppelingSchemaWhenRequested":0.003,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\AangebodenGebruikServiceDecompositionTest::testResolveThrowsWhenSchemaMissing":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\AangebodenGebruikServiceDecompositionTest::testResolveThrowsWhenSettingsRaises":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ArchiMateExportServiceDecompositionTest::testCreateFolderNodeAttachesChildWithStandardAttributes":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ArchiMateExportServiceDecompositionTest::testCreateFolderNodeAttachesToParent":0.005,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ArchiMateExportServiceDecompositionTest::testCreateFolderNodeReturnsTheNewChild":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ArchiMateImportServiceDecompositionTest::testValidateAcceptsCamelCaseKey":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ArchiMateImportServiceDecompositionTest::testValidateAcceptsSnakeCaseKey":0.005,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ArchiMateImportServiceDecompositionTest::testValidateThrowsWhenPathMissing":0.011,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ArchiMateImportServiceDecompositionTest::testValidateThrowsWhenPathEmpty":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ArchiMateImportServiceDecompositionTest::testValidateThrowsWhenFileMissing":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ArchiMateImportServiceDecompositionTest::testValidatePrefersCamelCaseOverSnakeCase":0.002,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ArchiMateServiceDecompositionTest::testResolveOrgRegisterAndSchemaPrefersVoorzieningenKeys":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ArchiMateServiceDecompositionTest::testResolveOrgRegisterAndSchemaFallsBackWhenRegisterEmpty":0.005,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ArchiMateServiceDecompositionTest::testResolveOrgRegisterAndSchemaFallsBackWhenSchemaMissing":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ArchiMateServiceDecompositionTest::testResolveOrgRegisterAndSchemaReturnsBothNullWhenNothingResolves":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ContactpersoonServiceDecompositionTest::testReturnsTrueForValidEmail":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ContactpersoonServiceDecompositionTest::testReturnsFalseAndWarnsForEmptyEmail":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ContactpersoonServiceDecompositionTest::testReturnsFalseAndWarnsForMalformedEmail":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ContactpersoonServiceDecompositionTest::testReturnsFalseForEmailWithoutAt":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\GebruikServiceGetApplicationIdsTest::testGetApplicationIdsWithObjectEntityReturnsIds":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\GebruikServiceGetApplicationIdsTest::testGetApplicationIdsWithArrayResultsReturnsIds":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\GebruikSyncServiceDecompositionTest::testExtractStatusDateMapProjectsAllStatuses":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\GebruikSyncServiceDecompositionTest::testResolveLatestEligibleStatusPicksLatestPastDate":0.002,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\GebruikSyncServiceDecompositionTest::testResolveLatestEligibleStatusAllFutureReturnsNulls":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\GebruikSyncServiceDecompositionTest::testResolveLatestEligibleStatusSkipsUnparseableDates":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ModuleComplianceServiceDecompositionTest::testNormaliseReturnsArrayUnchanged":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ModuleComplianceServiceDecompositionTest::testNormaliseCoercesNonArrayToEmpty":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ModuleComplianceServiceDecompositionTest::testExtractedHelpersExistAndArePrivate":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ModuleRegistrationServiceDecompositionTest::testMapOrgTypeToRegisteredByKnownTypes":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ModuleRegistrationServiceDecompositionTest::testMapOrgTypeToRegisteredByUnknownReturnsNull":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ModuleRegistrationServiceDecompositionTest::testResolveOrganisationTypeWithoutObjectServiceReturnsNull":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ModuleVersionServiceDecompositionTest::testCompareVersionsTrueWhenVersionsExist":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ModuleVersionServiceDecompositionTest::testCompareVersionsFalseWhenNoVersions":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ModuleVersionServiceDecompositionTest::testDecomposedHelpersExistAndArePrivate":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\OrganizationSyncServiceDecompositionTest::testHandleSyncErrorAppendsToStatsAndLogs":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\OrganizationSyncServiceDecompositionTest::testHandleSyncErrorSurvivesMissingErrorsKey":0.005,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\OrganizationSyncServiceDecompositionTest::testBuildInitialSyncStatsShape":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\OrganizationSyncServiceDecompositionTest::testValidateOrgSyncConfigHappyPath":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\OrganizationSyncServiceDecompositionTest::testValidateOrgSyncConfigEmptyInput":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\OrganizationSyncServiceDecompositionTest::testValidateOrgSyncConfigNonPositive":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\RegisterFragmentMergeTest::testDisjointFragmentsUnionSchemasAndPaths":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\RegisterFragmentMergeTest::testListsConcatenateAndScalarsOverwrite":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SettingsServiceDecompositionTest::testBuildObjectTypeStatusEntryReportsConfiguredWhenBothPresent":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SettingsServiceDecompositionTest::testBuildObjectTypeStatusEntryReportsUnconfiguredWhenSchemaMissing":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SettingsServiceDecompositionTest::testGetConfigurationStatusDelegatesToHelperForBothObjectTypes":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SettingsServiceResolverWiringTest::testGetSchemaIdRoutesThroughResolverWhenAvailable":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SettingsServiceResolverWiringTest::testGetSchemaIdFallsBackToLegacyConfigWhenResolverEmpty":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SettingsServiceResolverWiringTest::testGetRegisterIdRoutesThroughResolverWhenAvailable":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SettingsServiceResolverWiringTest::testGetSchemaIdSkipsResolverWhenOpenRegisterAbsent":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SoftwareCatalogue\\ContactPersonHandlerDecompositionTest::testCleanLowercasesAndStripsNonAlphanumeric":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SoftwareCatalogue\\ContactPersonHandlerDecompositionTest::testCleanReturnsEmptyPairWhenEitherSideMissing":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SoftwareCatalogue\\ContactPersonHandlerDecompositionTest::testCleanStripsAccentsAndPunctuation":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SoftwareCatalogue\\ContactPersonHandlerDecompositionTest::testCleanKeepsDigits":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SoftwareCatalogue\\GroupHandlerDecompositionTest::testAssignOrganizationGroupSkipsEmptyGroupId":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SoftwareCatalogue\\GroupHandlerDecompositionTest::testAssignOrganizationGroupAddsUserWhenNotMember":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SoftwareCatalogue\\GroupHandlerDecompositionTest::testAssignOrganizationGroupSkipsExistingMember":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SoftwareCatalogue\\GroupHandlerDecompositionTest::testAssignOrganizationGroupSkipsMissingGroup":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SoftwareCatalogue\\HierarchyHandlerDecompositionTest::testResolvePrimaryManagerPicksFirst":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SoftwareCatalogue\\HierarchyHandlerDecompositionTest::testAssignManagerForCurrentUserDelegatesWhenNotBeheerder":0.002,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SoftwareCatalogue\\HierarchyHandlerDecompositionTest::testAssignManagerForCurrentUserNoopWhenBeheerder":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SoftwareCatalogue\\HierarchyHandlerDecompositionTest::testAssignManagerForOtherBeheerdersSingleNoop":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SoftwareCatalogue\\HierarchyHandlerDecompositionTest::testAssignManagerForOtherBeheerdersPointsAtPrimary":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SoftwareCatalogue\\OrganizationHandlerDecompositionTest::testTitleFromFullName":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SoftwareCatalogue\\OrganizationHandlerDecompositionTest::testTitleSkipsEmptyTussenvoegsel":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SoftwareCatalogue\\OrganizationHandlerDecompositionTest::testTitleFallsBackToEmail":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SoftwareCatalogue\\OrganizationHandlerDecompositionTest::testTitleFallsBackToLiteralWhenAllAbsent":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SoftwareCatalogue\\OrganizationHandlerDecompositionTest::testTitlePrefersNameOverEmail":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SoftwareCatalogueServiceDecompositionTest::testResolveVoorzieningenContextReturnsTupleWhenConfigured":0.004,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SoftwareCatalogueServiceDecompositionTest::testResolveVoorzieningenContextReturnsNullWhenRegisterMissing":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SoftwareCatalogueServiceDecompositionTest::testResolveVoorzieningenContextReturnsNullWhenSchemaMissing":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SoftwareCatalogueServiceDecompositionTest::testResolveVoorzieningenContextLogsContextLabelOnFailure":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SymfonyEmailServiceDecompositionTest::testRenderTemplateUsesCustomOverride":0.002,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SymfonyEmailServiceDecompositionTest::testRenderTemplateFallsBackToDefault":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SymfonyEmailServiceDecompositionTest::testResolveSenderReturnsConfiguredTuple":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SymfonyEmailServiceDecompositionTest::testResolveSenderUsesDefaultsWhenSettingsEmpty":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SymfonyEmailServiceDecompositionTest::testEnsureEmailDeliveryReadySkipsWhenUnconfigured":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SymfonyEmailServiceDecompositionTest::testEnsureEmailDeliveryReadySkipsWhenTypeDisabled":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\SymfonyEmailServiceDecompositionTest::testEnsureEmailDeliveryReadyPasses":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\FederationServiceTest::testUnavailableWithoutOpenCatalogi":0.005,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\FederationServiceTest::testAnnounceDegradesWithoutOpenCatalogi":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\FederationServiceTest::testAnnounceNoopWhenDisabled":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\FederationServiceTest::testDiscoverPeersDegrades":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\FederationServiceTest::testIsPeerSourced":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\FederationServiceTest::testPeerHostGuard":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\FederationServiceTest::testLocalFederationAllowlist":0.003,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ContractApprovalServiceTest::testDelegationNotConfiguredWhenDecideskAbsent":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ContractApprovalServiceTest::testSubmitFailsClosedWhenDelegationNotConfigured":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ContractApprovalServiceTest::testIsDecisionForContractRejectsBlankId":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ContractApprovalServiceTest::testResolveContractForOutcomeFailsClosedOnBlankDecisionId":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ContractApprovalServiceTest::testProjectOutcomeUnknownContractIsNoop":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ContractStatusServiceTest::testActiveWithPastEndDateExpires":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ContractStatusServiceTest::testActiveWithFutureEndDateDoesNotExpire":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ContractStatusServiceTest::testActiveWithoutEndDateDoesNotExpire":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ContractStatusServiceTest::testUnparseableEndDateDoesNotExpire":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ContractStatusServiceTest::testNegotiationStatusNeverExpires":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ContractStatusServiceTest::testAlreadyExpiredIsNotReprocessed":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ContractStatusServiceTest::testExpirePastContractsDegradesWithoutOpenRegister":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\LifecycleRegisterShapeTest::testGebruikHasOptionalReplacementFields":0.014,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\LifecycleRegisterShapeTest::testGebruikDeclaresPhaseoutRule":0.013,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\LifecycleRegisterShapeTest::testModuleVersieDeclaresEolRule":0.012,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ModuleComplianceServiceTest::testExtractResolvesAllRelationShapes":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ModuleComplianceServiceTest::testExtractDeduplicates":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ModuleComplianceServiceTest::testExtractSkipsRecordsWithoutStandaardversie":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ModuleComplianceServiceTest::testLoopGuardIgnoresOrder":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ModuleComplianceServiceTest::testLoopGuardDetectsChange":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ModuleComplianceServiceTest::testNormaliseCoercesNonArrayToEmpty":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\OpenDataRegisterShapeTest::testOrganisatieHasModerationField":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testShouldIncludeGebruikReturnsTrueWhenFlagIsTrue":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testShouldIncludeGebruikReturnsFalseWhenFlagAbsent":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testShouldIncludeDeelnamesGebruikReturnsTrueWhenFlagIsTrue":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testShouldIncludeDeelnamesGebruikReturnsFalseWhenOnlyGebruikSet":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testBothFlagsAreIndependent":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testGetAppliedEnrichmentsIncludesDeelnamesWhenFlagSet":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testGetAppliedEnrichmentsIncludesGebruikWhenFlagSet":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testGetAppliedEnrichmentsReturnsEmptyArrayWhenNoFlagsSet":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testProcessGebruikItemsSetsRegularType":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testProcessGebruikItemsAttachesSourceOrgMetadataForDeelnames":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testProcessGebruikItemsFallsBackToSelfOrgWhenAfnemerAbsent":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testProcessGebruikItemsSkipsItemsWithoutElementRef":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testGetNodeGebruikReturnsItemsForMatchingElementRef":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testGetNodeGebruikReturnsEmptyArrayForUnknownRef":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testGetNodeDeelnamesGebruikReturnsDeelnamesItems":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testDeduplicationRemovesDeelnamesWhenOwnedExists":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testDeduplicationKeepsAllDeelnamesWhenNoOwnedGebruik":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\PublicationServiceTest::testPublishSetsPublicatiedatum":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\PublicationServiceTest::testPublishWithFutureMomentSchedules":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\PublicationServiceTest::testDepublishClearsPublicatiedatum":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\PublicationServiceTest::testNonPublishableTypeRejected":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\PublicationServiceTest::testPublishableTypes":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\PublishGateRbacTest::testEveryPublishableSchemaHasTheGate":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\PublishGateRbacTest::testAnonReadVisibleOnlyWhenPublicatiedatumInThePast":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\PublishGateRbacTest::testPublishGateFieldsPresent":0.004,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\FederationServiceTest::testPublishEntryForFederationDelegatesToPublicationService":0.007,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\FederationServiceTest::testPublishEntryForFederationDegradesWithoutPublicationService":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\FederationServiceTest::testStatusReportsPerPeerStaleAndAllowedState":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\FederationServiceTest::testAddPeer":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\FederationServiceTest::testRemovePeer":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\FederationServiceTest::testPullPeerMergesNewEntries":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\FederationServiceTest::testPullPeerIsIdempotentAndLeavesLocalEntriesAlone":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\FederationServiceTest::testPullPeerMarksStaleAfterFailureThreshold":0.009,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\FederationServiceTest::testPullPeerBlockedBySsrfGuard":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\FederationMergerTest::testNewPeerEntryIsCreatedWithProvenance":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\FederationMergerTest::testInboundSourceCannotBeSpoofed":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\FederationMergerTest::testChangedPeerEntryIsUpdated":0.008,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\FederationMergerTest::testUnchangedRepullIsIdempotent":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\FederationMergerTest::testRemovedPeerEntryIsWithdrawn":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\FederationMergerTest::testOtherPeersMirrorsAreUntouched":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\FederationMergerTest::testEntryWithoutStableIdIsSkipped":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\FederationMergerTest::testStalenessThreshold":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\FederationMergerTest::testApplyStale":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\IntakeModerationTest::testAnonymousSubmissionLandsPendingAndUnpublished":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\IntakeModerationTest::testPrivilegedKeysAreStripped":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\IntakeModerationTest::testMissingRequiredFieldRejected":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\IntakeModerationTest::testOversizedValueRejected":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\IntakeModerationTest::testDuplicatePendingRefused":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\IntakeModerationTest::testApprovalActivatesAndPublishes":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\IntakeModerationTest::testRejectionStaysUnpublished":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\IntakeModerationTest::testNonPendingCannotBeApproved":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\IntakeModerationTest::testPeerSourcedCannotBeModerated":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\IntakeModerationTest::testListPending":0}} \ No newline at end of file diff --git a/.phpunit.result.cache b/.phpunit.result.cache deleted file mode 100644 index 056b1a3f..00000000 --- a/.phpunit.result.cache +++ /dev/null @@ -1 +0,0 @@ -{"version":2,"defects":[],"times":{"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testShouldIncludeGebruikReturnsTrueWhenFlagIsTrue":0.06,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testShouldIncludeGebruikReturnsFalseWhenFlagAbsent":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testShouldIncludeDeelnamesGebruikReturnsTrueWhenFlagIsTrue":0.005,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testShouldIncludeDeelnamesGebruikReturnsFalseWhenOnlyGebruikSet":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testBothFlagsAreIndependent":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testGetAppliedEnrichmentsIncludesDeelnamesWhenFlagSet":0.007,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testGetAppliedEnrichmentsIncludesGebruikWhenFlagSet":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testGetAppliedEnrichmentsReturnsEmptyArrayWhenNoFlagsSet":0.002,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testProcessGebruikItemsSetsRegularType":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testProcessGebruikItemsAttachesSourceOrgMetadataForDeelnames":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testProcessGebruikItemsFallsBackToSelfOrgWhenAfnemerAbsent":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testProcessGebruikItemsSkipsItemsWithoutElementRef":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testGetNodeGebruikReturnsItemsForMatchingElementRef":0.006,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testGetNodeGebruikReturnsEmptyArrayForUnknownRef":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testGetNodeDeelnamesGebruikReturnsDeelnamesItems":0,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testDeduplicationRemovesDeelnamesWhenOwnedExists":0.001,"OCA\\SoftwareCatalog\\Tests\\Unit\\Service\\ViewServiceTest::testDeduplicationKeepsAllDeelnamesWhenNoOwnedGebruik":0}} \ No newline at end of file diff --git a/lib/Service/SbomImportService.php b/lib/Service/SbomImportService.php index 20ffd4fb..d1284ee4 100644 --- a/lib/Service/SbomImportService.php +++ b/lib/Service/SbomImportService.php @@ -298,7 +298,7 @@ public function userCanReadModule(string $moduleUuid): bool * * @return array `{sbomLastImportedAt, sbomFormat, sbomFileName, progress}`. * - * @spec openspec/specs/sbom-import/spec.md#requirement-modulversie-records-sbom-import-provenance + * @spec openspec/specs/sbom-import/spec.md#requirement-moduleversie-records-sbom-import-provenance */ public function getStatus(string $moduleVersieUuid, ?string $operationId=null): array { @@ -450,7 +450,7 @@ private function createComponentSet( * * @return void * - * @spec openspec/specs/sbom-import/spec.md#requirement-modulversie-records-sbom-import-provenance + * @spec openspec/specs/sbom-import/spec.md#requirement-moduleversie-records-sbom-import-provenance */ private function recordProvenance( ObjectService $objectService, diff --git a/lib/Settings/softwarecatalogus_register.json b/lib/Settings/softwarecatalogus_register.json index 68cd302c..851ff06d 100644 --- a/lib/Settings/softwarecatalogus_register.json +++ b/lib/Settings/softwarecatalogus_register.json @@ -4192,7 +4192,7 @@ "$ref": "", "items": { "cascadeDelete": true, - "$ref": "#/components/schemas/property", + "$ref": "#/components/schemas/property-definition", "type": "object" }, "objectConfiguration": { @@ -5356,7 +5356,7 @@ "$ref": "", "items": { "cascadeDelete": true, - "$ref": "#/components/schemas/property", + "$ref": "#/components/schemas/property-definition", "type": "object" }, "objectConfiguration": { @@ -5803,7 +5803,7 @@ "$ref": "", "items": { "cascadeDelete": true, - "$ref": "#/components/schemas/property", + "$ref": "#/components/schemas/property-definition", "type": "object" }, "objectConfiguration": { @@ -6632,7 +6632,7 @@ "$ref": "", "items": { "cascadeDelete": true, - "$ref": "#/components/schemas/property", + "$ref": "#/components/schemas/property-definition", "type": "object" }, "objectConfiguration": { @@ -8018,11 +8018,13 @@ "properties": { "alg": { "type": "string", - "title": "Algorithm" + "title": "Algorithm", + "description": "Naam van het hash-algoritme zoals CycloneDX het aanlevert, bijvoorbeeld SHA-256 of SHA-512." }, "value": { "type": "string", - "title": "Value" + "title": "Value", + "description": "De hexadecimale hashwaarde die met het genoemde algoritme over het componentbestand is berekend." } } } diff --git a/openspec/specs/sbom-import/spec.md b/openspec/specs/sbom-import/spec.md index de41c119..fb4b0f4d 100644 --- a/openspec/specs/sbom-import/spec.md +++ b/openspec/specs/sbom-import/spec.md @@ -224,3 +224,23 @@ unset. - **THEN** existing `moduleVersie` objects without the new fields load and save unchanged + +## Notes + +### SPDX 2.x is a second parser entry point, not a second requirement + +`SbomParserService` exposes two explicit entry points rather than one +auto-detecting `parse()`: `parse()` for CycloneDX and `parseSpdx()` for SPDX +2.x JSON. Both normalise to the same component DTO shape +(`name`/`version`/`purl`/`licenses`); SPDX carries no VEX-equivalent block in +this app's scope, so `parseSpdx()` always returns an empty `vulnerabilities` +list and no component can arrive with a confirmed CVE match through that path. +`spdxVersion` values outside `SPDX-2.*` are rejected with +`UnsupportedSbomFormatException`, mirroring the CycloneDX `bomFormat` / +`specVersion` rejection above. + +This is recorded as a note rather than as a Requirement because the SPDX path +has unit coverage (`tests/Unit/SbomParserServiceTest.php`) but no browser-level +proof; promoting it to a Requirement means writing the Scenarios and the +Playwright test that assert them, which is follow-up work rather than something +to declare satisfied here. diff --git a/src/manifest.json b/src/manifest.json index f162c430..0c6a751b 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -157,14 +157,6 @@ "route": "FeaturesRoadmap", "section": "footer", "order": 95 - }, - { - "id": "SettingsMenu", - "label": "Settings", - "icon": "CogOutline", - "route": "Settings", - "section": "settings", - "order": 99 } ], "pages": [ @@ -827,26 +819,6 @@ "config": { "documentationUrl": "https://softwarecatalog.conduction.nl" } - }, - { - "id": "Settings", - "route": "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/settings", - "type": "settings", - "title": "Settings", - "config": { - "saveEndpoint": "/index.php/apps/softwarecatalog/api/settings", - "sections": [ - { - "title": "Algemeen", - "widgets": [ - { - "type": "component", - "componentName": "SoftwareCatalogSettingsPage" - } - ] - } - ] - } } ] } diff --git a/src/menu-layout.json b/src/menu-layout.json index f4709284..6b9c26b5 100644 --- a/src/menu-layout.json +++ b/src/menu-layout.json @@ -7,7 +7,5 @@ "ComplianceMatrix": "ReportsCompliance" }, "removals": [], - "settingsSection": [ - "SettingsMenu" - ] + "settingsSection": [] } diff --git a/src/utils/suiteWizard.js b/src/utils/suiteWizard.js index b0477dff..3213c471 100644 --- a/src/utils/suiteWizard.js +++ b/src/utils/suiteWizard.js @@ -105,7 +105,7 @@ export function summarizeApplications(applications) { * * @return {Array<{uuid: string, label: string, raw: object}>} Option list. * - * @spec openspec/specs/suite-wizard/spec.md#requirement-the-wizard-must-let-the-user-attach-one-or-more-existing-applications-to-the-new-suite + * @spec openspec/specs/suite-wizard/spec.md#requirement-the-wizard-shall-guide-suite-creation-through-details-application-attachment-and-confirmation-steps */ export function mapApplicationOptions(collection) { const modules = Array.isArray(collection) ? collection : (collection?.results || []) diff --git a/test-setup.sh b/test-setup.sh index 96a07989..14efa8e8 100644 --- a/test-setup.sh +++ b/test-setup.sh @@ -798,7 +798,7 @@ else: echo "" echo "--- Step 8b: Importing AMEF test data ---" -AMEF_FILE="/var/www/html/custom_apps/softwarecatalog/data/GEMMA release.xml" +AMEF_FILE="/var/www/html/custom_apps/softwarecatalog/tests/fixtures/amef/GEMMA release.xml" if docker exec nextcloud test -f "$AMEF_FILE"; then # Check if AMEF views already exist (full GEMMA release has 248 views) VIEW_COUNT=$(curl -s -u "${ADMIN_USER}:${ADMIN_PASS}" \ diff --git a/tests/e2e/manifest-pages.spec.ts b/tests/e2e/manifest-pages.spec.ts index 488b091a..95a4a2b0 100644 --- a/tests/e2e/manifest-pages.spec.ts +++ b/tests/e2e/manifest-pages.spec.ts @@ -209,38 +209,56 @@ for (const p of DETAIL_PAGES) { } // --------------------------------------------------------------------------- -// Settings page (type: settings) — in-app settings surface +// Settings — the Nextcloud admin settings section // --------------------------------------------------------------------------- +// These tests used to drive the in-app `#/settings` route, a manifest +// `type: "settings"` page. ADR-079 D1 removed it: app-level configuration has +// exactly one home, `/settings/admin/`, where Nextcloud authorizes the +// caller server-side before the section renders. The SAME component +// (`src/views/settings/SoftwareCatalogSettings.vue`) renders there, mounted by +// `src/settings.js` into `templates/settings/admin.php`, so these assertions +// are unchanged in substance — only the door they walk through moved. +// +// `domcontentloaded`, not `networkidle`: Nextcloud keeps long-lived polls open, +// so the network never goes idle (ADR-074 rule 4). The visibility assertions +// below are the real readiness signal. +const ADMIN_SETTINGS_URL = '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/settings/admin/softwarecatalog' + +/** + * Open the app's Nextcloud admin settings section and return its host element. + * Auth is injected from storageState (see playwright.config.ts). + */ +async function gotoAdminSettings(page: Page) { + await page.goto(ADMIN_SETTINGS_URL, { waitUntil: 'domcontentloaded' }) + const host = page.locator('#softwarecatalog-settings') + await expect(host).toBeVisible({ timeout: 30000 }) + return host +} + // The settings shell (SoftwareCatalogSettings.vue) renders its section // navigation and the configuration status — fe-settings-ui "Open settings". // @e2e fe-settings-ui::open-settings -test('manifest settings: in-app settings page renders', async ({ page }) => { - await gotoAppRoute(page, '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/settings') - const main = page.locator(APP_MAIN).first() - await expect(main).toBeVisible() - // Scope to main so the assertion can't match a transient notification toast - // elsewhere in the DOM (which also contains app/section words but is hidden). - await expect(main.getByText('SoftwareCatalog', { exact: false }).first()).toBeVisible({ timeout: 30000 }) +test('admin settings: the settings section renders', async ({ page }) => { + const host = await gotoAdminSettings(page) + // Scope to the app's own settings host so the assertion can't match a + // transient notification toast elsewhere in the DOM. + await expect(host.getByText('SoftwareCatalog', { exact: false }).first()).toBeVisible({ timeout: 30000 }) }) // The settings shell renders the Statistics overview section (StatisticsOverview.vue), // which loads and displays aggregate object counts — fe-settings-ui "View statistics". // @e2e fe-settings-ui::view-statistics -test('manifest settings: statistics section renders', async ({ page }) => { - await gotoAppRoute(page, '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/settings') - const main = page.locator(APP_MAIN).first() - await expect(main).toBeVisible() - await expect(main.getByText('Statistics', { exact: false }).first()).toBeVisible({ timeout: 30000 }) +test('admin settings: statistics section renders', async ({ page }) => { + const host = await gotoAdminSettings(page) + await expect(host.getByText('Statistics', { exact: false }).first()).toBeVisible({ timeout: 30000 }) }) // The settings shell renders the Version information section (VersionInformation.vue), // which loads and displays the app version — fe-settings-ui "View version information". // @e2e fe-settings-ui::view-version-information -test('manifest settings: version information section renders', async ({ page }) => { - await gotoAppRoute(page, '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/settings') - const main = page.locator(APP_MAIN).first() - await expect(main).toBeVisible() - // Match the "Version Information" section heading inside main, not a hidden - // "Application Version was updated" notification toast in the DOM. - await expect(main.getByText('Version Information', { exact: false }).first()).toBeVisible({ timeout: 30000 }) +test('admin settings: version information section renders', async ({ page }) => { + const host = await gotoAdminSettings(page) + // Match the "Version Information" section heading inside the settings host, + // not a hidden "Application Version was updated" notification toast. + await expect(host.getByText('Version Information', { exact: false }).first()).toBeVisible({ timeout: 30000 }) }) diff --git a/data/GEMMA release.xml b/tests/fixtures/amef/GEMMA release.xml similarity index 100% rename from data/GEMMA release.xml rename to tests/fixtures/amef/GEMMA release.xml From 878b0127bd04de7810d7f53d71ece956242b7f3c Mon Sep 17 00:00:00 2001 From: Ruben van der Linde Date: Sun, 9 Aug 2026 17:18:29 +0200 Subject: [PATCH 2/2] test(e2e): retarget the settings-coverage suite at /settings/admin/softwarecatalog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The five failures on this branch were all in tests/e2e/spec-coverage/settings.spec.ts, which still navigated to the in-app '#/settings' route that ADR-079 D1 removed. Same component, same assertions, different door: gotoSettings() now opens the Nextcloud admin settings section and scopes to #softwarecatalog-settings, the host element templates/settings/admin.php provides. The tests were retargeted rather than deleted or skipped — they are the only browser-level proof that Version Information, Object Statistics, General Settings, OpenRegister Integration, User Groups and Organization Synchronization still render, and that the OpenRegister sub-tabs switch. --- tests/e2e/spec-coverage/settings.spec.ts | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/tests/e2e/spec-coverage/settings.spec.ts b/tests/e2e/spec-coverage/settings.spec.ts index b21cc2a8..b3277bb1 100644 --- a/tests/e2e/spec-coverage/settings.spec.ts +++ b/tests/e2e/spec-coverage/settings.spec.ts @@ -1,8 +1,15 @@ // SPDX-License-Identifier: EUPL-1.2 // SPDX-FileCopyrightText: 2026 Conduction B.V. /** - * Behavioural UI coverage for the in-app Settings page (manifest page - * `Settings` → SoftwareCatalogSettings.vue). + * Behavioural UI coverage for the app's settings surface + * (`/settings/admin/softwarecatalog` → SoftwareCatalogSettings.vue). + * + * This drove the in-app manifest page `Settings` until ADR-079 D1 removed it: + * app-level configuration has exactly one home, the Nextcloud admin settings + * section, which the platform authorizes server-side before it renders. The + * SAME component renders there — mounted by `src/settings.js` into + * `templates/settings/admin.php` — so every assertion below is unchanged; only + * the door they walk through moved. * * The existing manifest-pages smoke asserts only three section TITLES exist. * This suite drives the real settings surface and its interactions: @@ -19,11 +26,18 @@ * longer filters that message, so this suite asserts it is genuinely absent. */ import { test, expect } from '@playwright/test' -import { gotoAppRoute, collectAppErrors, expectNoAppErrors, APP_MAIN } from './_helpers' +import { collectAppErrors, expectNoAppErrors } from './_helpers' +/** + * Open the app's Nextcloud admin settings section and return its host element. + * + * `domcontentloaded`, not `networkidle`: Nextcloud keeps long-lived polls open, + * so the network never goes idle (ADR-074 rule 4). The banner assertion below + * is the real readiness signal. + */ async function gotoSettings(page) { - await gotoAppRoute(page, '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/settings') - const main = page.locator(APP_MAIN).first() + await page.goto('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/settings/admin/softwarecatalog', { waitUntil: 'domcontentloaded' }) + const main = page.locator('#softwarecatalog-settings') // The settings shell renders the app name banner first. await expect(main.getByText('SoftwareCatalog', { exact: false }).first()) .toBeVisible({ timeout: 30000 })