From 90e3b6c9ba60f043db7954e5820e82650f3938d3 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Wed, 3 Sep 2025 15:42:23 +0200 Subject: [PATCH 001/180] Add date validation to risk analysis --- .../src/services/catalogService.ts | 8 ++++-- .../src/services/validators.ts | 13 +++++++-- .../risk-analysis/riskAnalysisValidation.ts | 22 ++++++++------- .../riskAnalysisValidationErrors.ts | 8 +++--- .../commons/src/risk-analysis/rules/PA/1.0.ts | 1 + .../commons/src/risk-analysis/rules/PA/2.0.ts | 1 + .../commons/src/risk-analysis/rules/PA/3.0.ts | 1 + .../src/risk-analysis/rules/PRIVATE/1.0.ts | 1 + .../src/risk-analysis/rules/PRIVATE/2.0.ts | 1 + .../rules/riskAnalysisFormRules.ts | 1 + .../src/services/eserviceTemplateService.ts | 16 ++++++++--- .../src/services/validators.ts | 3 +- .../src/services/purposeService.ts | 28 +++++++++++++------ .../src/services/validators.ts | 15 +++++++--- 14 files changed, 83 insertions(+), 36 deletions(-) diff --git a/packages/catalog-process/src/services/catalogService.ts b/packages/catalog-process/src/services/catalogService.ts index b88c16995c..9325aad6dd 100644 --- a/packages/catalog-process/src/services/catalogService.ts +++ b/packages/catalog-process/src/services/catalogService.ts @@ -2173,7 +2173,9 @@ export function catalogServiceBuilder( const validatedRiskAnalysisForm = validateRiskAnalysisSchemaOrThrow( eserviceRiskAnalysisSeed.riskAnalysisForm, - tenant.kind + tenant.kind, + new Date() // [todo remove comment] risk analysis creation + // drawback: the date of the risk analysis is set below in the function riskAnalysisValidatedFormToNewRiskAnalysis ); const newRiskAnalysis: RiskAnalysis = @@ -2249,7 +2251,9 @@ export function catalogServiceBuilder( const validatedRiskAnalysisForm = validateRiskAnalysisSchemaOrThrow( eserviceRiskAnalysisSeed.riskAnalysisForm, - tenant.kind + tenant.kind, + new Date() // [todo remove comment] risk analysis update + // drawback: the date of the risk analysis is replaced below in the function riskAnalysisValidatedFormToNewRiskAnalysis ); const updatedRiskAnalysis: RiskAnalysis = { diff --git a/packages/catalog-process/src/services/validators.ts b/packages/catalog-process/src/services/validators.ts index 44893d9fff..98316496c4 100644 --- a/packages/catalog-process/src/services/validators.ts +++ b/packages/catalog-process/src/services/validators.ts @@ -202,9 +202,15 @@ export function assertHasNoDraftOrWaitingForApprovalDescriptor( export function validateRiskAnalysisSchemaOrThrow( riskAnalysisForm: catalogApi.EServiceRiskAnalysisSeed["riskAnalysisForm"], - tenantKind: TenantKind + tenantKind: TenantKind, + dateForValidation: Date ): RiskAnalysisValidatedForm { - const result = validateRiskAnalysis(riskAnalysisForm, true, tenantKind); + const result = validateRiskAnalysis( + riskAnalysisForm, + true, + tenantKind, + dateForValidation + ); if (result.type === "invalid") { throw riskAnalysisValidationFailed(result.issues); } else { @@ -226,7 +232,8 @@ export function assertRiskAnalysisIsValidForPublication( riskAnalysis.riskAnalysisForm ), false, - tenantKind + tenantKind, + riskAnalysis.createdAt ); if (result.type === "invalid") { diff --git a/packages/commons/src/risk-analysis/riskAnalysisValidation.ts b/packages/commons/src/risk-analysis/riskAnalysisValidation.ts index 581a35b7f6..9afaae8ad4 100644 --- a/packages/commons/src/risk-analysis/riskAnalysisValidation.ts +++ b/packages/commons/src/risk-analysis/riskAnalysisValidation.ts @@ -12,13 +12,13 @@ import { import { RiskAnalysisValidationIssue, dependencyNotFoundError, + expiredRulesVersionError, missingExpectedFieldError, noRulesVersionFoundError, unexpectedDependencyValueError, unexpectedFieldError, unexpectedFieldFormatError, unexpectedFieldValueError, - unexpectedRulesVersionError, } from "./riskAnalysisValidationErrors.js"; import { FormQuestionRules, @@ -30,21 +30,23 @@ import { riskAnalysisFormRules } from "./rules/riskAnalysisFormRulesProvider.js" export function validateRiskAnalysis( riskAnalysisForm: RiskAnalysisFormToValidate, schemaOnlyValidation: boolean, - tenantKind: TenantKind + tenantKind: TenantKind, + dateForValidation: Date ): RiskAnalysisValidationResult { - const latestVersionFormRules = getLatestVersionFormRules(tenantKind); + const formRulesForValidation = getFormRulesByVersion( + tenantKind, + riskAnalysisForm.version + ); - if (latestVersionFormRules === undefined) { + if (formRulesForValidation === undefined) { return invalidResult([noRulesVersionFoundError(tenantKind)]); } - if (latestVersionFormRules.version !== riskAnalysisForm.version) { - return invalidResult([ - unexpectedRulesVersionError(riskAnalysisForm.version), - ]); + if (formRulesForValidation.expiration < dateForValidation) { + return invalidResult([expiredRulesVersionError(riskAnalysisForm.version)]); } - const validationRules = buildValidationRules(latestVersionFormRules); + const validationRules = buildValidationRules(formRulesForValidation); const sanitizedAnswers = getSanitizedAnswers(riskAnalysisForm); @@ -84,7 +86,7 @@ export function validateRiskAnalysis( ); return validResult({ - version: latestVersionFormRules.version, + version: formRulesForValidation.version, singleAnswers, multiAnswers, }); diff --git a/packages/commons/src/risk-analysis/riskAnalysisValidationErrors.ts b/packages/commons/src/risk-analysis/riskAnalysisValidationErrors.ts index 6acfc7f330..ee714f6cf0 100644 --- a/packages/commons/src/risk-analysis/riskAnalysisValidationErrors.ts +++ b/packages/commons/src/risk-analysis/riskAnalysisValidationErrors.ts @@ -2,7 +2,7 @@ import { InternalError, TenantKind } from "pagopa-interop-models"; type RiskAnalysisValidationIssueCode = | "noRulesVersionFoundError" - | "unexpectedRulesVersionError" + | "expiredRulesVersionError" | "unexpectedFieldError" | "unexpectedFieldValueError" | "dependencyNotFoundError" @@ -31,12 +31,12 @@ export function noRulesVersionFoundError( }); } -export function unexpectedRulesVersionError( +export function expiredRulesVersionError( version: string ): RiskAnalysisValidationIssue { return new RiskAnalysisValidationIssue({ - code: "unexpectedRulesVersionError", - detail: `Unexpected ruleset version ${version}`, + code: "expiredRulesVersionError", + detail: `Expired ruleset version ${version}`, }); } diff --git a/packages/commons/src/risk-analysis/rules/PA/1.0.ts b/packages/commons/src/risk-analysis/rules/PA/1.0.ts index 85c9763617..30e230891b 100644 --- a/packages/commons/src/risk-analysis/rules/PA/1.0.ts +++ b/packages/commons/src/risk-analysis/rules/PA/1.0.ts @@ -1,5 +1,6 @@ export const pa1 = { version: "1.0", + expiration: new Date("2025-01-01"), questions: [ { id: "purpose", diff --git a/packages/commons/src/risk-analysis/rules/PA/2.0.ts b/packages/commons/src/risk-analysis/rules/PA/2.0.ts index 617570d225..a2d7c2376e 100644 --- a/packages/commons/src/risk-analysis/rules/PA/2.0.ts +++ b/packages/commons/src/risk-analysis/rules/PA/2.0.ts @@ -1,5 +1,6 @@ export const pa2 = { version: "2.0", + expiration: new Date("2025-01-01"), questions: [ { id: "purpose", diff --git a/packages/commons/src/risk-analysis/rules/PA/3.0.ts b/packages/commons/src/risk-analysis/rules/PA/3.0.ts index a3caf6bed5..06023f2ab9 100644 --- a/packages/commons/src/risk-analysis/rules/PA/3.0.ts +++ b/packages/commons/src/risk-analysis/rules/PA/3.0.ts @@ -1,5 +1,6 @@ export const pa3 = { version: "3.0", + expiration: new Date("2026-01-01"), questions: [ { id: "purpose", diff --git a/packages/commons/src/risk-analysis/rules/PRIVATE/1.0.ts b/packages/commons/src/risk-analysis/rules/PRIVATE/1.0.ts index 5cff8a5e24..920697ad0b 100644 --- a/packages/commons/src/risk-analysis/rules/PRIVATE/1.0.ts +++ b/packages/commons/src/risk-analysis/rules/PRIVATE/1.0.ts @@ -1,5 +1,6 @@ export const private1 = { version: "1.0", + expiration: new Date("2025-01-01"), questions: [ { id: "purpose", diff --git a/packages/commons/src/risk-analysis/rules/PRIVATE/2.0.ts b/packages/commons/src/risk-analysis/rules/PRIVATE/2.0.ts index 8b041d7e80..6e1692b144 100644 --- a/packages/commons/src/risk-analysis/rules/PRIVATE/2.0.ts +++ b/packages/commons/src/risk-analysis/rules/PRIVATE/2.0.ts @@ -1,5 +1,6 @@ export const private2 = { version: "2.0", + expiration: new Date("2026-01-01"), questions: [ { id: "purpose", diff --git a/packages/commons/src/risk-analysis/rules/riskAnalysisFormRules.ts b/packages/commons/src/risk-analysis/rules/riskAnalysisFormRules.ts index d54517ffcc..791e70ed44 100644 --- a/packages/commons/src/risk-analysis/rules/riskAnalysisFormRules.ts +++ b/packages/commons/src/risk-analysis/rules/riskAnalysisFormRules.ts @@ -75,6 +75,7 @@ export type FormQuestionRules = z.infer; export const RiskAnalysisFormRules = z.object({ version: z.string(), + expiration: z.date(), questions: z.array(FormQuestionRules), }); export type RiskAnalysisFormRules = z.infer; diff --git a/packages/eservice-template-process/src/services/eserviceTemplateService.ts b/packages/eservice-template-process/src/services/eserviceTemplateService.ts index b613f88452..cae536b1a9 100644 --- a/packages/eservice-template-process/src/services/eserviceTemplateService.ts +++ b/packages/eservice-template-process/src/services/eserviceTemplateService.ts @@ -239,9 +239,15 @@ const replaceEServiceTemplateVersion = ( export function validateRiskAnalysisSchemaOrThrow( riskAnalysisForm: eserviceTemplateApi.EServiceTemplateRiskAnalysisSeed["riskAnalysisForm"], - tenantKind: TenantKind + tenantKind: TenantKind, + dateForValidation: Date ): RiskAnalysisValidatedForm { - const result = validateRiskAnalysis(riskAnalysisForm, true, tenantKind); + const result = validateRiskAnalysis( + riskAnalysisForm, + true, + tenantKind, + dateForValidation + ); if (result.type === "invalid") { throw riskAnalysisValidationFailed(result.issues); } else { @@ -880,7 +886,8 @@ export function eserviceTemplateServiceBuilder( const validatedRiskAnalysisForm = validateRiskAnalysisSchemaOrThrow( createRiskAnalysis.riskAnalysisForm, - createRiskAnalysis.tenantKind + createRiskAnalysis.tenantKind, + new Date() ); const newRiskAnalysis: EServiceTemplateRiskAnalysis = @@ -965,7 +972,8 @@ export function eserviceTemplateServiceBuilder( const validatedForm = validateRiskAnalysisSchemaOrThrow( updateRiskAnalysisSeed.riskAnalysisForm, - updateRiskAnalysisSeed.tenantKind + updateRiskAnalysisSeed.tenantKind, + riskAnalysisToUpdate.createdAt ); const updatedRiskAnalysisForm: RiskAnalysisForm = { diff --git a/packages/eservice-template-process/src/services/validators.ts b/packages/eservice-template-process/src/services/validators.ts index 039a0c46fc..871b3c2227 100644 --- a/packages/eservice-template-process/src/services/validators.ts +++ b/packages/eservice-template-process/src/services/validators.ts @@ -163,7 +163,8 @@ export function assertRiskAnalysisIsValidForPublication( riskAnalysis.riskAnalysisForm ), false, - riskAnalysis.tenantKind + riskAnalysis.tenantKind, + riskAnalysis.createdAt ); if (result.type === "invalid") { diff --git a/packages/purpose-process/src/services/purposeService.ts b/packages/purpose-process/src/services/purposeService.ts index b852dcc8eb..1ed0dfb075 100644 --- a/packages/purpose-process/src/services/purposeService.ts +++ b/packages/purpose-process/src/services/purposeService.ts @@ -288,7 +288,8 @@ export function purposeServiceBuilder( ? isRiskAnalysisFormValid( purpose.data.riskAnalysisForm, false, - tenantKind + tenantKind, + purpose.data.createdAt ) : true; @@ -826,7 +827,8 @@ export function purposeServiceBuilder( ? isRiskAnalysisFormValid( purpose.data.riskAnalysisForm, false, - tenantKind + tenantKind, + purpose.data.createdAt ) : true; @@ -979,6 +981,7 @@ export function purposeServiceBuilder( riskAnalysisFormToRiskAnalysisFormToValidate(riskAnalysisForm), schemaOnlyValidation: false, tenantKind, + dateForValidation: purpose.data.createdAt, }); } @@ -1210,10 +1213,13 @@ export function purposeServiceBuilder( readModelService ); + const createdAt = new Date(); + const validatedFormSeed = validateAndTransformRiskAnalysis( purposeSeed.riskAnalysisForm, false, - await retrieveTenantKind(authData.organizationId, readModelService) + await retrieveTenantKind(authData.organizationId, readModelService), + createdAt ); await retrieveActiveAgreement(eserviceId, consumerId, readModelService); @@ -1229,7 +1235,7 @@ export function purposeServiceBuilder( id: generateId(), title: purposeSeed.title, description: purposeSeed.description, - createdAt: new Date(), + createdAt, eserviceId, consumerId, delegationId, @@ -1304,17 +1310,20 @@ export function purposeServiceBuilder( title: seed.title, }); + const createdAt = new Date(); + validateRiskAnalysisOrThrow({ riskAnalysisForm: riskAnalysisFormToRiskAnalysisFormToValidate( riskAnalysis.riskAnalysisForm ), schemaOnlyValidation: false, tenantKind: producerKind, + dateForValidation: createdAt, }); const newVersion: PurposeVersion = { id: generateId(), - createdAt: new Date(), + createdAt, state: purposeVersionState.draft, dailyCalls: seed.dailyCalls, }; @@ -1449,7 +1458,8 @@ export function purposeServiceBuilder( clonedRiskAnalysisForm ), false, - tenantKind + tenantKind, + currentDate ).type === "valid" : false; @@ -1626,7 +1636,8 @@ const performUpdatePurpose = async ( ? validateAndTransformRiskAnalysis( updateContent.riskAnalysisForm, true, - tenantKind + tenantKind, + purpose.data.createdAt ) : purpose.data.riskAnalysisForm; @@ -1659,7 +1670,8 @@ const performUpdatePurpose = async ( isRiskAnalysisValid: isRiskAnalysisFormValid( updatedPurpose.riskAnalysisForm, false, - tenantKind + tenantKind, + purpose.data.createdAt ), }; }; diff --git a/packages/purpose-process/src/services/validators.ts b/packages/purpose-process/src/services/validators.ts index 67196b6f25..87f3c0b824 100644 --- a/packages/purpose-process/src/services/validators.ts +++ b/packages/purpose-process/src/services/validators.ts @@ -48,7 +48,8 @@ import { export const isRiskAnalysisFormValid = ( riskAnalysisForm: RiskAnalysisForm | undefined, schemaOnlyValidation: boolean, - tenantKind: TenantKind + tenantKind: TenantKind, + dateForValidation: Date ): boolean => { if (riskAnalysisForm === undefined) { return false; @@ -57,7 +58,8 @@ export const isRiskAnalysisFormValid = ( validateRiskAnalysis( riskAnalysisFormToRiskAnalysisFormToValidate(riskAnalysisForm), schemaOnlyValidation, - tenantKind + tenantKind, + dateForValidation ).type === "valid" ); } @@ -113,15 +115,18 @@ export function validateRiskAnalysisOrThrow({ riskAnalysisForm, schemaOnlyValidation, tenantKind, + dateForValidation, }: { riskAnalysisForm: purposeApi.RiskAnalysisFormSeed; schemaOnlyValidation: boolean; tenantKind: TenantKind; + dateForValidation: Date; }): RiskAnalysisValidatedForm { const result = validateRiskAnalysis( riskAnalysisForm, schemaOnlyValidation, - tenantKind + tenantKind, + dateForValidation ); if (result.type === "invalid") { throw riskAnalysisValidationFailed(result.issues); @@ -133,7 +138,8 @@ export function validateRiskAnalysisOrThrow({ export function validateAndTransformRiskAnalysis( riskAnalysisForm: purposeApi.RiskAnalysisFormSeed | undefined, schemaOnlyValidation: boolean, - tenantKind: TenantKind + tenantKind: TenantKind, + dateForValidation: Date ): PurposeRiskAnalysisForm | undefined { if (!riskAnalysisForm) { return undefined; @@ -142,6 +148,7 @@ export function validateAndTransformRiskAnalysis( riskAnalysisForm, schemaOnlyValidation, tenantKind, + dateForValidation, }); return { From 3fa95c2ae4103fc303a4cd55f2390a1188363743 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Fri, 5 Sep 2025 14:37:13 +0200 Subject: [PATCH 002/180] Make expiration optional --- packages/commons/src/risk-analysis/riskAnalysisValidation.ts | 5 ++++- packages/commons/src/risk-analysis/rules/PA/3.0.ts | 1 - packages/commons/src/risk-analysis/rules/PRIVATE/2.0.ts | 1 - .../commons/src/risk-analysis/rules/riskAnalysisFormRules.ts | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/commons/src/risk-analysis/riskAnalysisValidation.ts b/packages/commons/src/risk-analysis/riskAnalysisValidation.ts index 9afaae8ad4..2fd9ea1bfa 100644 --- a/packages/commons/src/risk-analysis/riskAnalysisValidation.ts +++ b/packages/commons/src/risk-analysis/riskAnalysisValidation.ts @@ -42,7 +42,10 @@ export function validateRiskAnalysis( return invalidResult([noRulesVersionFoundError(tenantKind)]); } - if (formRulesForValidation.expiration < dateForValidation) { + if ( + formRulesForValidation.expiration && + formRulesForValidation.expiration < dateForValidation + ) { return invalidResult([expiredRulesVersionError(riskAnalysisForm.version)]); } diff --git a/packages/commons/src/risk-analysis/rules/PA/3.0.ts b/packages/commons/src/risk-analysis/rules/PA/3.0.ts index 06023f2ab9..a3caf6bed5 100644 --- a/packages/commons/src/risk-analysis/rules/PA/3.0.ts +++ b/packages/commons/src/risk-analysis/rules/PA/3.0.ts @@ -1,6 +1,5 @@ export const pa3 = { version: "3.0", - expiration: new Date("2026-01-01"), questions: [ { id: "purpose", diff --git a/packages/commons/src/risk-analysis/rules/PRIVATE/2.0.ts b/packages/commons/src/risk-analysis/rules/PRIVATE/2.0.ts index 6e1692b144..8b041d7e80 100644 --- a/packages/commons/src/risk-analysis/rules/PRIVATE/2.0.ts +++ b/packages/commons/src/risk-analysis/rules/PRIVATE/2.0.ts @@ -1,6 +1,5 @@ export const private2 = { version: "2.0", - expiration: new Date("2026-01-01"), questions: [ { id: "purpose", diff --git a/packages/commons/src/risk-analysis/rules/riskAnalysisFormRules.ts b/packages/commons/src/risk-analysis/rules/riskAnalysisFormRules.ts index 791e70ed44..a3eb9288e5 100644 --- a/packages/commons/src/risk-analysis/rules/riskAnalysisFormRules.ts +++ b/packages/commons/src/risk-analysis/rules/riskAnalysisFormRules.ts @@ -75,7 +75,7 @@ export type FormQuestionRules = z.infer; export const RiskAnalysisFormRules = z.object({ version: z.string(), - expiration: z.date(), + expiration: z.date().optional(), questions: z.array(FormQuestionRules), }); export type RiskAnalysisFormRules = z.infer; From fc68c693c40e5a15d4357650ab34ae20522b222d Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Fri, 5 Sep 2025 15:42:09 +0200 Subject: [PATCH 003/180] Use current date for validation in creation/update --- packages/catalog-process/src/services/validators.ts | 2 +- .../src/services/eserviceTemplateService.ts | 2 +- .../eservice-template-process/src/services/validators.ts | 2 +- packages/purpose-process/src/services/purposeService.ts | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/catalog-process/src/services/validators.ts b/packages/catalog-process/src/services/validators.ts index 98316496c4..b21a0ce950 100644 --- a/packages/catalog-process/src/services/validators.ts +++ b/packages/catalog-process/src/services/validators.ts @@ -233,7 +233,7 @@ export function assertRiskAnalysisIsValidForPublication( ), false, tenantKind, - riskAnalysis.createdAt + new Date() ); if (result.type === "invalid") { diff --git a/packages/eservice-template-process/src/services/eserviceTemplateService.ts b/packages/eservice-template-process/src/services/eserviceTemplateService.ts index cae536b1a9..35967a0997 100644 --- a/packages/eservice-template-process/src/services/eserviceTemplateService.ts +++ b/packages/eservice-template-process/src/services/eserviceTemplateService.ts @@ -973,7 +973,7 @@ export function eserviceTemplateServiceBuilder( const validatedForm = validateRiskAnalysisSchemaOrThrow( updateRiskAnalysisSeed.riskAnalysisForm, updateRiskAnalysisSeed.tenantKind, - riskAnalysisToUpdate.createdAt + new Date() ); const updatedRiskAnalysisForm: RiskAnalysisForm = { diff --git a/packages/eservice-template-process/src/services/validators.ts b/packages/eservice-template-process/src/services/validators.ts index 871b3c2227..fc78063c55 100644 --- a/packages/eservice-template-process/src/services/validators.ts +++ b/packages/eservice-template-process/src/services/validators.ts @@ -164,7 +164,7 @@ export function assertRiskAnalysisIsValidForPublication( ), false, riskAnalysis.tenantKind, - riskAnalysis.createdAt + new Date() ); if (result.type === "invalid") { diff --git a/packages/purpose-process/src/services/purposeService.ts b/packages/purpose-process/src/services/purposeService.ts index 1ed0dfb075..699ccd55a8 100644 --- a/packages/purpose-process/src/services/purposeService.ts +++ b/packages/purpose-process/src/services/purposeService.ts @@ -828,7 +828,7 @@ export function purposeServiceBuilder( purpose.data.riskAnalysisForm, false, tenantKind, - purpose.data.createdAt + new Date() ) : true; @@ -981,7 +981,7 @@ export function purposeServiceBuilder( riskAnalysisFormToRiskAnalysisFormToValidate(riskAnalysisForm), schemaOnlyValidation: false, tenantKind, - dateForValidation: purpose.data.createdAt, + dateForValidation: new Date(), // beware: if the purpose version was waiting for approval, a new RA might have been published }); } @@ -1637,7 +1637,7 @@ const performUpdatePurpose = async ( updateContent.riskAnalysisForm, true, tenantKind, - purpose.data.createdAt + new Date() ) : purpose.data.riskAnalysisForm; @@ -1671,7 +1671,7 @@ const performUpdatePurpose = async ( updatedPurpose.riskAnalysisForm, false, tenantKind, - purpose.data.createdAt + new Date() ), }; }; From 34cbeba743cc60bb8efa08a6e37e3a48af31efe8 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 8 Sep 2025 11:32:22 +0200 Subject: [PATCH 004/180] Update tests --- ...riskAnalysisValidation.integration.test.ts | 213 ++++++++++-------- .../risk-analysis/riskAnalysisValidation.ts | 6 +- .../riskAnalysisValidationErrors.ts | 11 +- .../test/api/createRiskAnalysis.test.ts | 2 +- .../publishEServiceTemplateVersion.test.ts | 2 +- .../test/api/updateRiskAnalysis.test.ts | 2 +- .../publishEServiceTemplateVersion.test.ts | 4 +- .../activatePurposeVersion.test.ts | 3 +- .../test/integration/createPurpose.test.ts | 7 +- .../integration/createReversePurpose.test.ts | 7 +- .../test/integration/updatePurpose.test.ts | 4 +- 11 files changed, 149 insertions(+), 112 deletions(-) diff --git a/packages/commons-test/test/riskAnalysisValidation.integration.test.ts b/packages/commons-test/test/riskAnalysisValidation.integration.test.ts index c60c4b6af0..a144b13a62 100644 --- a/packages/commons-test/test/riskAnalysisValidation.integration.test.ts +++ b/packages/commons-test/test/riskAnalysisValidation.integration.test.ts @@ -8,8 +8,8 @@ import { unexpectedDependencyValueError, unexpectedFieldError, unexpectedFieldValueError, - unexpectedRulesVersionError, validateRiskAnalysis, + rulesVersionNotFoundError, } from "pagopa-interop-commons"; import { validRiskAnalysis2_0_Private, @@ -21,12 +21,18 @@ import { } from "../src/riskAnalysisTestUtils.js"; describe("Risk Analysis Validation", () => { - it("should succeed on correct form 3.0 on tenant kind PA", () => { - const result = validateRiskAnalysis(validRiskAnalysis3_0_Pa, false, "PA"); + it("should succeed on correct form 3.0 (not expired) on tenant kind PA", () => { + const result = validateRiskAnalysis( + validRiskAnalysis3_0_Pa, + false, + "PA", + new Date() + ); const resultSchemaOnly = validateRiskAnalysis( validRiskAnalysis3_0_Pa, true, - "PA" + "PA", + new Date() ); expect(result).toEqual({ type: "valid", @@ -35,7 +41,7 @@ describe("Risk Analysis Validation", () => { expect(result).toEqual(resultSchemaOnly); }); - it("should succeed on correct form 3.0 schema only on tenant kind PA", () => { + it("should succeed on correct form 3.0 (not expired) schema only on tenant kind PA", () => { const expected: RiskAnalysisValidatedForm = { version: validSchemaOnlyRiskAnalysis3_0_Pa.version, singleAnswers: [{ key: "purpose", value: "INSTITUTIONAL" }], @@ -45,7 +51,8 @@ describe("Risk Analysis Validation", () => { const result = validateRiskAnalysis( validSchemaOnlyRiskAnalysis3_0_Pa, true, - "PA" + "PA", + new Date() ); expect(result).toEqual({ @@ -54,16 +61,18 @@ describe("Risk Analysis Validation", () => { }); }); - it("should succeed on correct form 2.0 on tenant kind PRIVATE", () => { + it("should succeed on correct form 2.0 (not expired) on tenant kind PRIVATE", () => { const result = validateRiskAnalysis( validRiskAnalysis2_0_Private, false, - "PRIVATE" + "PRIVATE", + new Date() ); const resultSchemaOnly = validateRiskAnalysis( validRiskAnalysis2_0_Private, true, - "PRIVATE" + "PRIVATE", + new Date() ); expect(result).toEqual({ @@ -73,7 +82,7 @@ describe("Risk Analysis Validation", () => { expect(result).toEqual(resultSchemaOnly); }); - it("should succeed on correct form 2.0 schema only on tenant kind PRIVATE", () => { + it("should succeed on correct form 2.0 (not expired) schema only on tenant kind PRIVATE", () => { const expected: RiskAnalysisValidatedForm = { version: validSchemaOnlyRiskAnalysis2_0_Private.version, singleAnswers: [{ key: "purpose", value: "INSTITUTIONAL" }], @@ -83,7 +92,8 @@ describe("Risk Analysis Validation", () => { const result = validateRiskAnalysis( validSchemaOnlyRiskAnalysis2_0_Private, true, - "PRIVATE" + "PRIVATE", + new Date() ); expect(result).toEqual({ @@ -92,16 +102,18 @@ describe("Risk Analysis Validation", () => { }); }); - it("should succeed on correct form 2.0 on tenant kind GSP", () => { + it("should succeed on correct form 2.0 (not expired) on tenant kind GSP", () => { const result = validateRiskAnalysis( validRiskAnalysis2_0_Private, false, - "GSP" + "GSP", + new Date() ); const resultSchemaOnly = validateRiskAnalysis( validRiskAnalysis2_0_Private, true, - "GSP" + "GSP", + new Date() ); expect(result).toEqual({ @@ -111,7 +123,7 @@ describe("Risk Analysis Validation", () => { expect(result).toEqual(resultSchemaOnly); }); - it("should succeed on correct form 2.0 schema only on tenant kind GSP", () => { + it("should succeed on correct form 2.0 (not expired) schema only on tenant kind GSP", () => { const expected: RiskAnalysisValidatedForm = { version: validSchemaOnlyRiskAnalysis2_0_Private.version, singleAnswers: [{ key: "purpose", value: "INSTITUTIONAL" }], @@ -121,7 +133,8 @@ describe("Risk Analysis Validation", () => { const result = validateRiskAnalysis( validSchemaOnlyRiskAnalysis2_0_Private, true, - "GSP" + "GSP", + new Date() ); expect(result).toEqual({ @@ -131,26 +144,30 @@ describe("Risk Analysis Validation", () => { }); it("should fail if version does not exists", () => { + const invalidVersionForPA = "9999.0"; const invalidRiskAnalysis: RiskAnalysisFormToValidate = { ...validRiskAnalysis3_0_Pa, - version: "9999.0", + version: invalidVersionForPA, }; - expect(validateRiskAnalysis(invalidRiskAnalysis, false, "PA")).toEqual({ + expect( + validateRiskAnalysis(invalidRiskAnalysis, false, "PA", new Date()) + ).toEqual({ type: "invalid", - issues: [unexpectedRulesVersionError(invalidRiskAnalysis.version)], + issues: [rulesVersionNotFoundError("PA", invalidVersionForPA)], }); + const invalidVersionForPrivate = "not a valid version"; const invalidRiskAnalysis2: RiskAnalysisFormToValidate = { ...validRiskAnalysis2_0_Private, - version: "not a valid version", + version: invalidVersionForPrivate, }; expect( - validateRiskAnalysis(invalidRiskAnalysis2, false, "PRIVATE") + validateRiskAnalysis(invalidRiskAnalysis2, false, "PRIVATE", new Date()) ).toEqual({ type: "invalid", - issues: [unexpectedRulesVersionError(invalidRiskAnalysis2.version)], + issues: [rulesVersionNotFoundError("PRIVATE", invalidVersionForPrivate)], }); }); @@ -166,15 +183,17 @@ describe("Risk Analysis Validation", () => { }, }; - expect(validateRiskAnalysis(riskAnalysis, false, "PA")).toEqual({ - type: "invalid", - issues: [ - dependencyNotFoundError("reasonPolicyNotProvided", "policyProvided"), - dependencyNotFoundError("confirmedDoneDpia", "doneDpia"), - missingExpectedFieldError("policyProvided"), - missingExpectedFieldError("doneDpia"), - ], - }); + expect(validateRiskAnalysis(riskAnalysis, false, "PA", new Date())).toEqual( + { + type: "invalid", + issues: [ + dependencyNotFoundError("reasonPolicyNotProvided", "policyProvided"), + dependencyNotFoundError("confirmedDoneDpia", "doneDpia"), + missingExpectedFieldError("policyProvided"), + missingExpectedFieldError("doneDpia"), + ], + } + ); }); it("should succeed schema only even if a provided answer depends on a missing field", () => { @@ -188,7 +207,7 @@ describe("Risk Analysis Validation", () => { }, }; - expect(validateRiskAnalysis(riskAnalysis, true, "PA")).toEqual({ + expect(validateRiskAnalysis(riskAnalysis, true, "PA", new Date())).toEqual({ type: "valid", value: { version: validRiskAnalysis3_0_Pa.version, @@ -213,27 +232,29 @@ describe("Risk Analysis Validation", () => { }, }; - expect(validateRiskAnalysis(riskAnalysis, false, "PA")).toEqual({ - type: "invalid", - issues: [ - unexpectedDependencyValueError( - "legalBasisPublicInterest", - "legalBasis", - "PUBLIC_INTEREST" - ), - unexpectedDependencyValueError( - "ruleOfLawText", - "legalBasisPublicInterest", - "RULE_OF_LAW" - ), - unexpectedDependencyValueError( - "ruleOfLawText", - "legalBasis", - "PUBLIC_INTEREST" - ), - unexpectedDependencyValueError("otherPurpose", "purpose", "OTHER"), - ], - }); + expect(validateRiskAnalysis(riskAnalysis, false, "PA", new Date())).toEqual( + { + type: "invalid", + issues: [ + unexpectedDependencyValueError( + "legalBasisPublicInterest", + "legalBasis", + "PUBLIC_INTEREST" + ), + unexpectedDependencyValueError( + "ruleOfLawText", + "legalBasisPublicInterest", + "RULE_OF_LAW" + ), + unexpectedDependencyValueError( + "ruleOfLawText", + "legalBasis", + "PUBLIC_INTEREST" + ), + unexpectedDependencyValueError("otherPurpose", "purpose", "OTHER"), + ], + } + ); }); it("should succeed schema only even if a provided answer depends on an existing field with an unexpected value", () => { @@ -247,7 +268,7 @@ describe("Risk Analysis Validation", () => { }, }; - expect(validateRiskAnalysis(riskAnalysis, true, "PA")).toEqual({ + expect(validateRiskAnalysis(riskAnalysis, true, "PA", new Date())).toEqual({ type: "valid", value: { version: riskAnalysis.version, @@ -276,13 +297,15 @@ describe("Risk Analysis Validation", () => { }, }; - expect(validateRiskAnalysis(riskAnalysis, false, "PA")).toEqual({ - type: "invalid", - issues: [ - missingExpectedFieldError("deliveryMethod"), - missingExpectedFieldError("doneDpia"), - ], - }); + expect(validateRiskAnalysis(riskAnalysis, false, "PA", new Date())).toEqual( + { + type: "invalid", + issues: [ + missingExpectedFieldError("deliveryMethod"), + missingExpectedFieldError("doneDpia"), + ], + } + ); }); it("should succeeed schema only even on missing expected answers", () => { @@ -297,7 +320,7 @@ describe("Risk Analysis Validation", () => { }, }; - expect(validateRiskAnalysis(riskAnalysis, true, "PA")).toEqual({ + expect(validateRiskAnalysis(riskAnalysis, true, "PA", new Date())).toEqual({ type: "valid", value: { version: riskAnalysis.version, @@ -323,18 +346,20 @@ describe("Risk Analysis Validation", () => { }, }; - expect(validateRiskAnalysis(riskAnalysis, false, "PA")).toEqual( - validateRiskAnalysis(riskAnalysis, true, "PA") + expect(validateRiskAnalysis(riskAnalysis, false, "PA", new Date())).toEqual( + validateRiskAnalysis(riskAnalysis, true, "PA", new Date()) ); - expect(validateRiskAnalysis(riskAnalysis, false, "PA")).toEqual({ - type: "invalid", - issues: [ - unexpectedFieldError("unexpectedFieldA"), - unexpectedFieldError("unexpectedFieldB"), - unexpectedFieldError("unexpectedFieldC"), - ], - }); + expect(validateRiskAnalysis(riskAnalysis, false, "PA", new Date())).toEqual( + { + type: "invalid", + issues: [ + unexpectedFieldError("unexpectedFieldA"), + unexpectedFieldError("unexpectedFieldB"), + unexpectedFieldError("unexpectedFieldC"), + ], + } + ); }); it("should fail on unexpected field value both schema only and not", () => { @@ -348,28 +373,30 @@ describe("Risk Analysis Validation", () => { }, }; - expect(validateRiskAnalysis(riskAnalysis, false, "PA")).toEqual( - validateRiskAnalysis(riskAnalysis, true, "PA") + expect(validateRiskAnalysis(riskAnalysis, false, "PA", new Date())).toEqual( + validateRiskAnalysis(riskAnalysis, true, "PA", new Date()) ); - expect(validateRiskAnalysis(riskAnalysis, false, "PA")).toEqual({ - type: "invalid", - issues: [ - unexpectedFieldValueError( - "purpose", - new Set(["INSTITUTIONAL", "OTHER"]) - ), - unexpectedFieldValueError( - "legalBasis", - new Set([ - "CONSENT", - "CONTRACT", - "LEGAL_OBLIGATION", - "SAFEGUARD", - "PUBLIC_INTEREST", - ]) - ), - ], - }); + expect(validateRiskAnalysis(riskAnalysis, false, "PA", new Date())).toEqual( + { + type: "invalid", + issues: [ + unexpectedFieldValueError( + "purpose", + new Set(["INSTITUTIONAL", "OTHER"]) + ), + unexpectedFieldValueError( + "legalBasis", + new Set([ + "CONSENT", + "CONTRACT", + "LEGAL_OBLIGATION", + "SAFEGUARD", + "PUBLIC_INTEREST", + ]) + ), + ], + } + ); }); }); diff --git a/packages/commons/src/risk-analysis/riskAnalysisValidation.ts b/packages/commons/src/risk-analysis/riskAnalysisValidation.ts index 2fd9ea1bfa..a5a90b0608 100644 --- a/packages/commons/src/risk-analysis/riskAnalysisValidation.ts +++ b/packages/commons/src/risk-analysis/riskAnalysisValidation.ts @@ -14,7 +14,7 @@ import { dependencyNotFoundError, expiredRulesVersionError, missingExpectedFieldError, - noRulesVersionFoundError, + rulesVersionNotFoundError, unexpectedDependencyValueError, unexpectedFieldError, unexpectedFieldFormatError, @@ -39,7 +39,9 @@ export function validateRiskAnalysis( ); if (formRulesForValidation === undefined) { - return invalidResult([noRulesVersionFoundError(tenantKind)]); + return invalidResult([ + rulesVersionNotFoundError(tenantKind, riskAnalysisForm.version), + ]); } if ( diff --git a/packages/commons/src/risk-analysis/riskAnalysisValidationErrors.ts b/packages/commons/src/risk-analysis/riskAnalysisValidationErrors.ts index ee714f6cf0..de900d702f 100644 --- a/packages/commons/src/risk-analysis/riskAnalysisValidationErrors.ts +++ b/packages/commons/src/risk-analysis/riskAnalysisValidationErrors.ts @@ -1,7 +1,7 @@ import { InternalError, TenantKind } from "pagopa-interop-models"; type RiskAnalysisValidationIssueCode = - | "noRulesVersionFoundError" + | "rulesVersionNotFoundError" | "expiredRulesVersionError" | "unexpectedFieldError" | "unexpectedFieldValueError" @@ -22,12 +22,13 @@ export class RiskAnalysisValidationIssue extends InternalError { { error: riskAnalysisValidationFailed([ new RiskAnalysisValidationIssue({ - code: "noRulesVersionFoundError", + code: "rulesVersionNotFoundError", detail: "no rule", }), ]), diff --git a/packages/eservice-template-process/test/api/publishEServiceTemplateVersion.test.ts b/packages/eservice-template-process/test/api/publishEServiceTemplateVersion.test.ts index 9f0fd8d540..e8c80d91e5 100644 --- a/packages/eservice-template-process/test/api/publishEServiceTemplateVersion.test.ts +++ b/packages/eservice-template-process/test/api/publishEServiceTemplateVersion.test.ts @@ -101,7 +101,7 @@ describe("API POST /templates/:templateId/versions/:templateVersionId/publish", { error: riskAnalysisValidationFailed([ new RiskAnalysisValidationIssue({ - code: "noRulesVersionFoundError", + code: "rulesVersionNotFoundError", detail: "no rule", }), ]), diff --git a/packages/eservice-template-process/test/api/updateRiskAnalysis.test.ts b/packages/eservice-template-process/test/api/updateRiskAnalysis.test.ts index 8d5115eb85..9cb8cbe356 100644 --- a/packages/eservice-template-process/test/api/updateRiskAnalysis.test.ts +++ b/packages/eservice-template-process/test/api/updateRiskAnalysis.test.ts @@ -119,7 +119,7 @@ describe("API POST /templates/:templateId/riskAnalysis/:riskAnalysisId", () => { { error: riskAnalysisValidationFailed([ new RiskAnalysisValidationIssue({ - code: "noRulesVersionFoundError", + code: "rulesVersionNotFoundError", detail: "no rule", }), ]), diff --git a/packages/eservice-template-process/test/integration/publishEServiceTemplateVersion.test.ts b/packages/eservice-template-process/test/integration/publishEServiceTemplateVersion.test.ts index f6a7207761..83ec0cc747 100644 --- a/packages/eservice-template-process/test/integration/publishEServiceTemplateVersion.test.ts +++ b/packages/eservice-template-process/test/integration/publishEServiceTemplateVersion.test.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable @typescript-eslint/no-floating-promises */ -import { unexpectedRulesVersionError } from "pagopa-interop-commons"; +import { expiredRulesVersionError } from "pagopa-interop-commons"; import { decodeProtobufPayload, getMockAuthData, @@ -336,7 +336,7 @@ describe("publishEServiceTemplateVersion", () => { }) ) ).rejects.toThrowError( - riskAnalysisValidationFailed([unexpectedRulesVersionError("0")]) + riskAnalysisValidationFailed([expiredRulesVersionError("0")]) ); }); diff --git a/packages/purpose-process/test/integration/activatePurposeVersion.test.ts b/packages/purpose-process/test/integration/activatePurposeVersion.test.ts index e72d8da54b..95fd78a8a9 100644 --- a/packages/purpose-process/test/integration/activatePurposeVersion.test.ts +++ b/packages/purpose-process/test/integration/activatePurposeVersion.test.ts @@ -1506,7 +1506,8 @@ describe("activatePurposeVersion", () => { const result = validateRiskAnalysis( riskAnalysisFormToRiskAnalysisFormToValidate(riskAnalysisForm), false, - mockConsumer.kind as TenantKind + mockConsumer.kind as TenantKind, + new Date() ); expect(async () => { diff --git a/packages/purpose-process/test/integration/createPurpose.test.ts b/packages/purpose-process/test/integration/createPurpose.test.ts index f3e66a8714..6fafcb11d8 100644 --- a/packages/purpose-process/test/integration/createPurpose.test.ts +++ b/packages/purpose-process/test/integration/createPurpose.test.ts @@ -35,7 +35,7 @@ import { getMockDelegation, getMockContext, } from "pagopa-interop-commons-test"; -import { unexpectedRulesVersionError } from "pagopa-interop-commons"; +import { rulesVersionNotFoundError } from "pagopa-interop-commons"; import { missingFreeOfChargeReason, tenantKindNotFound, @@ -571,7 +571,10 @@ describe("createPurpose", () => { ) ).rejects.toThrowError( riskAnalysisValidationFailed([ - unexpectedRulesVersionError(mockInvalidRiskAnalysisForm.version), + rulesVersionNotFoundError( + tenant.kind!, + mockInvalidRiskAnalysisForm.version + ), ]) ); }); diff --git a/packages/purpose-process/test/integration/createReversePurpose.test.ts b/packages/purpose-process/test/integration/createReversePurpose.test.ts index f0fac11e8c..16485cbd97 100644 --- a/packages/purpose-process/test/integration/createReversePurpose.test.ts +++ b/packages/purpose-process/test/integration/createReversePurpose.test.ts @@ -35,7 +35,7 @@ import { delegationState, TenantId, } from "pagopa-interop-models"; -import { unexpectedRulesVersionError } from "pagopa-interop-commons"; +import { rulesVersionNotFoundError } from "pagopa-interop-commons"; import { purposeApi } from "pagopa-interop-api-clients"; import { agreementNotFound, @@ -831,7 +831,10 @@ describe("createReversePurpose", () => { ) ).rejects.toThrowError( riskAnalysisValidationFailed([ - unexpectedRulesVersionError(mockRiskAnalysis.riskAnalysisForm.version), + rulesVersionNotFoundError( + tenantKind.PA, + mockRiskAnalysis.riskAnalysisForm.version + ), ]) ); }); diff --git a/packages/purpose-process/test/integration/updatePurpose.test.ts b/packages/purpose-process/test/integration/updatePurpose.test.ts index 277cfdbfb1..c3d31190fc 100644 --- a/packages/purpose-process/test/integration/updatePurpose.test.ts +++ b/packages/purpose-process/test/integration/updatePurpose.test.ts @@ -1,7 +1,7 @@ /* eslint-disable functional/no-let */ /* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable @typescript-eslint/no-floating-promises */ -import { unexpectedRulesVersionError } from "pagopa-interop-commons"; +import { expiredRulesVersionError } from "pagopa-interop-commons"; import { randomArrayItem, getMockTenant, @@ -810,7 +810,7 @@ describe("updatePurpose and updateReversePurpose", () => { getMockContext({ authData: getMockAuthData(tenant.id) }) ) ).rejects.toThrowError( - riskAnalysisValidationFailed([unexpectedRulesVersionError("0")]) + riskAnalysisValidationFailed([expiredRulesVersionError("0")]) ); }); it("should throw tenantIsNotTheDelegatedConsumer when the requester is the Consumer and is updating a purpose created by the delegate in updatePurpose", async () => { From 039ce7cb59de68c4bdda10345bab48f3906b1c13 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 8 Sep 2025 12:13:14 +0200 Subject: [PATCH 005/180] Fix test --- .../test/integration/publishEServiceTemplateVersion.test.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/eservice-template-process/test/integration/publishEServiceTemplateVersion.test.ts b/packages/eservice-template-process/test/integration/publishEServiceTemplateVersion.test.ts index 83ec0cc747..1a25ee3f03 100644 --- a/packages/eservice-template-process/test/integration/publishEServiceTemplateVersion.test.ts +++ b/packages/eservice-template-process/test/integration/publishEServiceTemplateVersion.test.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable @typescript-eslint/no-floating-promises */ -import { expiredRulesVersionError } from "pagopa-interop-commons"; +import { rulesVersionNotFoundError } from "pagopa-interop-commons"; import { decodeProtobufPayload, getMockAuthData, @@ -336,7 +336,9 @@ describe("publishEServiceTemplateVersion", () => { }) ) ).rejects.toThrowError( - riskAnalysisValidationFailed([expiredRulesVersionError("0")]) + riskAnalysisValidationFailed([ + rulesVersionNotFoundError(tenantKind.PA, "0"), + ]) ); }); From 467c736c41e74bae67d3f3dbec5aa233e994bfc3 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 8 Sep 2025 14:55:02 +0200 Subject: [PATCH 006/180] Fix test --- .../purpose-process/test/integration/updatePurpose.test.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/purpose-process/test/integration/updatePurpose.test.ts b/packages/purpose-process/test/integration/updatePurpose.test.ts index c3d31190fc..8c68adb38f 100644 --- a/packages/purpose-process/test/integration/updatePurpose.test.ts +++ b/packages/purpose-process/test/integration/updatePurpose.test.ts @@ -1,7 +1,7 @@ /* eslint-disable functional/no-let */ /* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable @typescript-eslint/no-floating-promises */ -import { expiredRulesVersionError } from "pagopa-interop-commons"; +import { rulesVersionNotFoundError } from "pagopa-interop-commons"; import { randomArrayItem, getMockTenant, @@ -810,7 +810,9 @@ describe("updatePurpose and updateReversePurpose", () => { getMockContext({ authData: getMockAuthData(tenant.id) }) ) ).rejects.toThrowError( - riskAnalysisValidationFailed([expiredRulesVersionError("0")]) + riskAnalysisValidationFailed([ + rulesVersionNotFoundError(tenant.kind!, "0"), + ]) ); }); it("should throw tenantIsNotTheDelegatedConsumer when the requester is the Consumer and is updating a purpose created by the delegate in updatePurpose", async () => { From 480145ed10b3035b24fd6e8d7248978205791eb2 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 8 Sep 2025 16:58:28 +0200 Subject: [PATCH 007/180] Setup feature flag --- packages/catalog-process/.env | 2 ++ packages/catalog-process/src/config/config.ts | 4 +++- .../commons/src/config/featureFlagsConfig.ts | 19 ++++++++++++++++++- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/packages/catalog-process/.env b/packages/catalog-process/.env index ba8de2c8f8..3acb37a66e 100644 --- a/packages/catalog-process/.env +++ b/packages/catalog-process/.env @@ -68,3 +68,5 @@ READMODEL_SQL_DB_SCHEMA_TENANT="readmodel_tenant" READMODEL_SQL_DB_SCHEMA_ESERVICE_TEMPLATE="readmodel_eservice_template" FEATURE_FLAG_AGREEMENT_APPROVAL_POLICY_UPDATE=true + +FEATURE_FLAG_ESERVICE_PERSONAL_DATA=false diff --git a/packages/catalog-process/src/config/config.ts b/packages/catalog-process/src/config/config.ts index b4078a8a38..d6dceb2bae 100644 --- a/packages/catalog-process/src/config/config.ts +++ b/packages/catalog-process/src/config/config.ts @@ -9,6 +9,7 @@ import { FeatureFlagSQLConfig, ReadModelSQLDbConfig, FeatureFlagAgreementApprovalPolicyUpdateConfig, + FeatureFlagEServicePersonalDataConfig, } from "pagopa-interop-commons"; import { z } from "zod"; @@ -45,7 +46,8 @@ const CatalogProcessConfig = CommonHTTPServiceConfig.and(ReadModelDbConfig) .and(EServiceTemplateS3Config) .and(ApplicationAuditProducerConfig) .and(FeatureFlagSQLConfig) - .and(ReadModelSQLDbConfig); + .and(ReadModelSQLDbConfig) + .and(FeatureFlagEServicePersonalDataConfig); export type CatalogProcessConfig = z.infer; diff --git a/packages/commons/src/config/featureFlagsConfig.ts b/packages/commons/src/config/featureFlagsConfig.ts index ac7a06924d..1aca129293 100644 --- a/packages/commons/src/config/featureFlagsConfig.ts +++ b/packages/commons/src/config/featureFlagsConfig.ts @@ -112,13 +112,30 @@ export type FeatureFlagNotificationConfig = z.infer< typeof FeatureFlagNotificationConfig >; +export const FeatureFlagEServicePersonalDataConfig = z + .object({ + FEATURE_FLAG_ESERVICE_PERSONAL_DATA: z + .enum(["true", "false"]) + .default("false") + .transform((value) => value === "true") + .optional(), + }) + .transform((c) => ({ + featureFlagEservicePersonalData: + c.FEATURE_FLAG_ESERVICE_PERSONAL_DATA ?? false, + })); +export type FeatureFlagEServicePersonalDataConfig = z.infer< + typeof FeatureFlagEServicePersonalDataConfig +>; + type FeatureFlags = FeatureFlagSignalhubWhitelistConfig & FeatureFlagAgreementApprovalPolicyUpdateConfig & FeatureFlagSQLConfig & FeatureFlagApplicationAuditStrictConfig & FeatureFlagImprovedProducerVerificationClaimsConfig & FeatureFlagClientAssertionStrictClaimsValidationConfig & - FeatureFlagNotificationConfig; + FeatureFlagNotificationConfig & + FeatureFlagEServicePersonalDataConfig; export type FeatureFlagKeys = keyof FeatureFlags & `featureFlag${string}`; From c35a470136f3c6851575a21f323b20cac199d7f4 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 8 Sep 2025 16:58:55 +0200 Subject: [PATCH 008/180] Add flag in eservice based on feature flag --- packages/api-clients/open-api/catalogApi.yml | 28 +++++++++++-------- .../src/services/catalogService.ts | 6 ++++ .../models/proto/v2/eservice/eservice.proto | 1 + packages/models/src/eservice/eservice.ts | 1 + .../readmodel-models/src/drizzle/schema.ts | 1 + packages/readmodel/src/catalog/splitters.ts | 1 + 6 files changed, 26 insertions(+), 12 deletions(-) diff --git a/packages/api-clients/open-api/catalogApi.yml b/packages/api-clients/open-api/catalogApi.yml index e811d7ad5d..5b39773647 100644 --- a/packages/api-clients/open-api/catalogApi.yml +++ b/packages/api-clients/open-api/catalogApi.yml @@ -178,8 +178,8 @@ paths: "200": description: EService created headers: - X-Metadata-Version: - $ref: "#/components/headers/MetadataVersionHeader" + X-Metadata-Version: + $ref: "#/components/headers/MetadataVersionHeader" content: application/json: schema: @@ -222,8 +222,8 @@ paths: schema: $ref: "#/components/schemas/EService" headers: - X-Metadata-Version: - $ref: "#/components/headers/MetadataVersionHeader" + X-Metadata-Version: + $ref: "#/components/headers/MetadataVersionHeader" "404": description: E-Service not found content: @@ -740,8 +740,8 @@ paths: "200": description: E-Service Descriptor suspended headers: - X-Metadata-Version: - $ref: "#/components/headers/MetadataVersionHeader" + X-Metadata-Version: + $ref: "#/components/headers/MetadataVersionHeader" content: application/json: schema: @@ -786,8 +786,8 @@ paths: "200": description: E-Service Descriptor suspended headers: - X-Metadata-Version: - $ref: "#/components/headers/MetadataVersionHeader" + X-Metadata-Version: + $ref: "#/components/headers/MetadataVersionHeader" content: application/json: schema: @@ -832,8 +832,8 @@ paths: "200": description: E-Service Descriptor activated headers: - X-Metadata-Version: - $ref: "#/components/headers/MetadataVersionHeader" + X-Metadata-Version: + $ref: "#/components/headers/MetadataVersionHeader" content: application/json: schema: @@ -1816,8 +1816,8 @@ paths: "200": description: New delegated e-service version approved headers: - X-Metadata-Version: - $ref: "#/components/headers/MetadataVersionHeader" + X-Metadata-Version: + $ref: "#/components/headers/MetadataVersionHeader" content: application/json: schema: @@ -2420,6 +2420,8 @@ components: type: boolean isClientAccessDelegable: type: boolean + personalData: + type: boolean UpdateEServiceSeed: type: object additionalProperties: false @@ -2447,6 +2449,8 @@ components: type: boolean isClientAccessDelegable: type: boolean + personalData: + type: boolean UpdateEServiceTemplateInstanceSeed: type: object additionalProperties: false diff --git a/packages/catalog-process/src/services/catalogService.ts b/packages/catalog-process/src/services/catalogService.ts index 9325aad6dd..013830e81d 100644 --- a/packages/catalog-process/src/services/catalogService.ts +++ b/packages/catalog-process/src/services/catalogService.ts @@ -529,6 +529,9 @@ async function innerCreateEService( .with(true, () => seed.isClientAccessDelegable) .exhaustive(), templateId: template?.id, + personalData: config.featureFlagEservicePersonalData + ? seed.personalData + : undefined, }; const eserviceCreationEvent = toCreateEventEServiceAdded( @@ -949,6 +952,9 @@ export function catalogServiceBuilder( .with(false, () => false) .with(true, () => eserviceSeed.isClientAccessDelegable) .exhaustive(), + personalData: config.featureFlagEservicePersonalData + ? eserviceSeed.personalData + : undefined, }; const event = toCreateEventEServiceUpdated( diff --git a/packages/models/proto/v2/eservice/eservice.proto b/packages/models/proto/v2/eservice/eservice.proto index 0c5314e0bb..f574a6b984 100644 --- a/packages/models/proto/v2/eservice/eservice.proto +++ b/packages/models/proto/v2/eservice/eservice.proto @@ -16,6 +16,7 @@ message EServiceV2 { optional bool isConsumerDelegable = 11; optional bool isClientAccessDelegable = 12; optional string templateId = 13; + optional bool personalData = 14; } message EServiceRiskAnalysisV2 { diff --git a/packages/models/src/eservice/eservice.ts b/packages/models/src/eservice/eservice.ts index 18f9cfba3f..7739bd234c 100644 --- a/packages/models/src/eservice/eservice.ts +++ b/packages/models/src/eservice/eservice.ts @@ -142,6 +142,7 @@ export const EService = z.object({ isConsumerDelegable: z.boolean().optional(), isClientAccessDelegable: z.boolean().optional(), templateId: EServiceTemplateId.optional(), + personalData: z.boolean().optional(), }); export type EService = z.infer; diff --git a/packages/readmodel-models/src/drizzle/schema.ts b/packages/readmodel-models/src/drizzle/schema.ts index 08d0ac918e..777b92d8eb 100644 --- a/packages/readmodel-models/src/drizzle/schema.ts +++ b/packages/readmodel-models/src/drizzle/schema.ts @@ -367,6 +367,7 @@ export const eserviceInReadmodelCatalog = readmodelCatalog.table( isConsumerDelegable: boolean("is_consumer_delegable"), isClientAccessDelegable: boolean("is_client_access_delegable"), templateId: uuid("template_id"), + personalData: boolean("personal_data"), }, (table) => [ unique("eservice_id_metadata_version_unique").on( diff --git a/packages/readmodel/src/catalog/splitters.ts b/packages/readmodel/src/catalog/splitters.ts index 0f3ab60f41..4ee79bab19 100644 --- a/packages/readmodel/src/catalog/splitters.ts +++ b/packages/readmodel/src/catalog/splitters.ts @@ -380,6 +380,7 @@ export const eserviceToEserviceSQL = ( isConsumerDelegable: eservice.isConsumerDelegable ?? null, isClientAccessDelegable: eservice.isClientAccessDelegable ?? null, templateId: eservice.templateId ?? null, + personalData: eservice.personalData ?? null, }); export const rejectionReasonToRejectionReasonSQL = ( From f7706f2752f7b6c70c6ee193f63b85c0ab535cb0 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 8 Sep 2025 16:59:53 +0200 Subject: [PATCH 009/180] Update eservice table --- docker/readmodel-db/catalog.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/docker/readmodel-db/catalog.sql b/docker/readmodel-db/catalog.sql index 2f0519d0af..e6cc6c9c6c 100644 --- a/docker/readmodel-db/catalog.sql +++ b/docker/readmodel-db/catalog.sql @@ -13,6 +13,7 @@ CREATE TABLE IF NOT EXISTS readmodel_catalog.eservice ( is_consumer_delegable BOOLEAN, is_client_access_delegable BOOLEAN, template_id UUID, + personal_data BOOLEAN, PRIMARY KEY (id), CONSTRAINT eservice_id_metadata_version_unique UNIQUE (id, metadata_version) ); From 5be532c710071d12b4b6b1bbe9b2184c71cece8d Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Tue, 9 Sep 2025 10:03:02 +0200 Subject: [PATCH 010/180] Update aggregator --- packages/readmodel/src/catalog/aggregators.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/readmodel/src/catalog/aggregators.ts b/packages/readmodel/src/catalog/aggregators.ts index 77b3960df9..ed7bb2c75b 100644 --- a/packages/readmodel/src/catalog/aggregators.ts +++ b/packages/readmodel/src/catalog/aggregators.ts @@ -284,6 +284,11 @@ export const aggregateEservice = ({ templateId: unsafeBrandId(eserviceSQL.templateId), } : {}), + ...(eserviceSQL.personalData + ? { + personalData: eserviceSQL.personalData, + } + : {}), }; return { data: eservice, From b94a28341966d3bc53dd7f9241d4141e211c742b Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Tue, 9 Sep 2025 10:03:07 +0200 Subject: [PATCH 011/180] Update tests --- packages/readmodel/test/eserviceAggregator.test.ts | 2 ++ packages/readmodel/test/eserviceSplitter.test.ts | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/packages/readmodel/test/eserviceAggregator.test.ts b/packages/readmodel/test/eserviceAggregator.test.ts index ed49b48061..518086efbc 100644 --- a/packages/readmodel/test/eserviceAggregator.test.ts +++ b/packages/readmodel/test/eserviceAggregator.test.ts @@ -44,6 +44,7 @@ describe("E-service aggregator", () => { termsAndConditionsUrl: "terms and conditions url", }, }; + const personalData = true; const descriptor: Descriptor = { ...getMockDescriptor(), @@ -72,6 +73,7 @@ describe("E-service aggregator", () => { isClientAccessDelegable, isConsumerDelegable, templateId, + personalData, }; const { diff --git a/packages/readmodel/test/eserviceSplitter.test.ts b/packages/readmodel/test/eserviceSplitter.test.ts index 3277da9170..46bf3c2f61 100644 --- a/packages/readmodel/test/eserviceSplitter.test.ts +++ b/packages/readmodel/test/eserviceSplitter.test.ts @@ -46,6 +46,7 @@ describe("E-service splitter", () => { const isClientAccessDelegable = true; const isConsumerDelegable = true; const templateId: EServiceTemplateId = generateId(); + const personalData = true; const templateVersionRef: EServiceTemplateVersionRef = { id: generateId(), @@ -84,6 +85,7 @@ describe("E-service splitter", () => { isClientAccessDelegable, isConsumerDelegable, templateId, + personalData, }; const { @@ -111,6 +113,7 @@ describe("E-service splitter", () => { isClientAccessDelegable, isConsumerDelegable, templateId, + personalData, }; const expectedRiskAnalysisSQL1: EServiceRiskAnalysisSQL = { @@ -259,6 +262,7 @@ describe("E-service splitter", () => { isSignalHubEnabled: false, isClientAccessDelegable: undefined, isConsumerDelegable: undefined, + personalData: undefined, }; const { @@ -286,6 +290,7 @@ describe("E-service splitter", () => { isClientAccessDelegable: null, isConsumerDelegable: null, templateId: null, + personalData: null, }; const expectedRiskAnalysisSQL1: EServiceRiskAnalysisSQL = { From 80ce6bcf3d85adf95bd0e39ac629654fefab537f Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Tue, 9 Sep 2025 10:50:05 +0200 Subject: [PATCH 012/180] Add new event --- packages/authorization-updater/src/index.ts | 3 ++- .../src/converters/toOutboundEventV2.ts | 1 + .../src/consumerServiceV2.ts | 1 + .../src/consumerServiceV2.ts | 1 + .../catalog-readmodel-writer/src/consumerServiceV2.ts | 1 + .../src/interfaceExporterV2.ts | 1 + .../src/handlers/catalog/consumerServiceV2.ts | 3 ++- .../src/handlers/eservices/handleEserviceEvent.ts | 3 ++- packages/models/proto/v2/eservice/events.proto | 5 +++-- packages/models/src/eservice/eserviceEvents.ts | 9 +++++++++ packages/notification-email-sender/src/index.ts | 3 ++- .../catalog/catalogItemEventNotificationConverter.ts | 1 + .../catalog/catalogItemEventNotificationMessage.ts | 1 + 13 files changed, 27 insertions(+), 6 deletions(-) diff --git a/packages/authorization-updater/src/index.ts b/packages/authorization-updater/src/index.ts index b5a59dd516..9de9095d0d 100644 --- a/packages/authorization-updater/src/index.ts +++ b/packages/authorization-updater/src/index.ts @@ -159,7 +159,8 @@ export async function sendCatalogAuthUpdate( "EServiceDescriptorDocumentUpdatedByTemplateUpdate", "EServiceDescriptorDocumentDeletedByTemplateUpdate", "EServiceSignalHubEnabled", - "EServiceSignalHubDisabled" + "EServiceSignalHubDisabled", + "EServicePersonalDataUpdatedAfterPublish" ), }, () => { diff --git a/packages/catalog-outbound-writer/src/converters/toOutboundEventV2.ts b/packages/catalog-outbound-writer/src/converters/toOutboundEventV2.ts index 35d4c08228..af0b1ec78f 100644 --- a/packages/catalog-outbound-writer/src/converters/toOutboundEventV2.ts +++ b/packages/catalog-outbound-writer/src/converters/toOutboundEventV2.ts @@ -212,6 +212,7 @@ export function toOutboundEventV2( { type: "EServiceRiskAnalysisAdded" }, { type: "EServiceRiskAnalysisDeleted" }, { type: "EServiceRiskAnalysisUpdated" }, + { type: "EServicePersonalDataUpdatedAfterPublish" }, // TODO move to the first handler after outbound gets updated () => undefined ) .exhaustive(); diff --git a/packages/catalog-platformstate-writer/src/consumerServiceV2.ts b/packages/catalog-platformstate-writer/src/consumerServiceV2.ts index 6d93c0c894..658538b612 100644 --- a/packages/catalog-platformstate-writer/src/consumerServiceV2.ts +++ b/packages/catalog-platformstate-writer/src/consumerServiceV2.ts @@ -303,6 +303,7 @@ export async function handleMessageV2( { type: "EServiceDescriptorDocumentDeletedByTemplateUpdate" }, { type: "EServiceSignalHubEnabled" }, { type: "EServiceSignalHubDisabled" }, + { type: "EServicePersonalDataUpdatedAfterPublish" }, () => Promise.resolve() ) .exhaustive(); diff --git a/packages/catalog-readmodel-writer-sql/src/consumerServiceV2.ts b/packages/catalog-readmodel-writer-sql/src/consumerServiceV2.ts index 56c61d8c8b..5fbb0ade53 100644 --- a/packages/catalog-readmodel-writer-sql/src/consumerServiceV2.ts +++ b/packages/catalog-readmodel-writer-sql/src/consumerServiceV2.ts @@ -59,6 +59,7 @@ export async function handleMessageV2( { type: "EServiceDescriptorDocumentDeletedByTemplateUpdate" }, { type: "EServiceSignalHubEnabled" }, { type: "EServiceSignalHubDisabled" }, + { type: "EServicePersonalDataUpdatedAfterPublish" }, async (message) => { const eservice = message.data.eservice; if (!eservice) { diff --git a/packages/catalog-readmodel-writer/src/consumerServiceV2.ts b/packages/catalog-readmodel-writer/src/consumerServiceV2.ts index e6e943db3b..0fc25098e2 100644 --- a/packages/catalog-readmodel-writer/src/consumerServiceV2.ts +++ b/packages/catalog-readmodel-writer/src/consumerServiceV2.ts @@ -60,6 +60,7 @@ export async function handleMessageV2( { type: "EServiceDescriptorDocumentDeletedByTemplateUpdate" }, { type: "EServiceSignalHubEnabled" }, { type: "EServiceSignalHubDisabled" }, + { type: "EServicePersonalDataUpdatedAfterPublish" }, async (message) => await eservices.updateOne( { diff --git a/packages/datalake-interface-exporter/src/interfaceExporterV2.ts b/packages/datalake-interface-exporter/src/interfaceExporterV2.ts index 29f18f85bd..44b62f79fd 100644 --- a/packages/datalake-interface-exporter/src/interfaceExporterV2.ts +++ b/packages/datalake-interface-exporter/src/interfaceExporterV2.ts @@ -74,6 +74,7 @@ export async function exportInterfaceV2( { type: "EServiceDescriptorDocumentDeletedByTemplateUpdate" }, { type: "EServiceSignalHubEnabled" }, { type: "EServiceSignalHubDisabled" }, + { type: "EServicePersonalDataUpdatedAfterPublish" }, () => undefined ) .exhaustive(); diff --git a/packages/domains-analytics-writer/src/handlers/catalog/consumerServiceV2.ts b/packages/domains-analytics-writer/src/handlers/catalog/consumerServiceV2.ts index 89bc0eda5e..f4afb62d5e 100644 --- a/packages/domains-analytics-writer/src/handlers/catalog/consumerServiceV2.ts +++ b/packages/domains-analytics-writer/src/handlers/catalog/consumerServiceV2.ts @@ -77,7 +77,8 @@ export async function handleCatalogMessageV2( "EServiceDescriptorDocumentDeleted", "EServiceDraftDescriptorDeleted", "EServiceSignalHubEnabled", - "EServiceSignalHubDisabled" + "EServiceSignalHubDisabled", + "EServicePersonalDataUpdatedAfterPublish" ), }, (msg) => { diff --git a/packages/in-app-notification-dispatcher/src/handlers/eservices/handleEserviceEvent.ts b/packages/in-app-notification-dispatcher/src/handlers/eservices/handleEserviceEvent.ts index b5229edb33..1c13963efe 100644 --- a/packages/in-app-notification-dispatcher/src/handlers/eservices/handleEserviceEvent.ts +++ b/packages/in-app-notification-dispatcher/src/handlers/eservices/handleEserviceEvent.ts @@ -85,7 +85,8 @@ export async function handleEServiceEvent( "EServiceDescriptorDocumentDeletedByTemplateUpdate", "EServiceDescriptorDocumentUpdatedByTemplateUpdate", "EServiceSignalHubEnabled", - "EServiceSignalHubDisabled" + "EServiceSignalHubDisabled", + "EServicePersonalDataUpdatedAfterPublish" ), }, () => { diff --git a/packages/models/proto/v2/eservice/events.proto b/packages/models/proto/v2/eservice/events.proto index 73f7c24931..35225a13b5 100644 --- a/packages/models/proto/v2/eservice/events.proto +++ b/packages/models/proto/v2/eservice/events.proto @@ -209,5 +209,6 @@ message EServiceSignalHubDisabledV2 { EServiceV2 eservice = 1; } - - +message EServicePersonalDataUpdatedAfterPublishV2 { + EServiceV2 eservice = 1; +} diff --git a/packages/models/src/eservice/eserviceEvents.ts b/packages/models/src/eservice/eserviceEvents.ts index e3435f0a9f..1c5e8cbd75 100644 --- a/packages/models/src/eservice/eserviceEvents.ts +++ b/packages/models/src/eservice/eserviceEvents.ts @@ -60,6 +60,7 @@ import { EServiceDescriptorAgreementApprovalPolicyUpdatedV2, EServiceSignalHubEnabledV2, EServiceSignalHubDisabledV2, + EServicePersonalDataUpdatedAfterPublishV2, } from "../gen/v2/eservice/events.js"; export function catalogEventToBinaryData(event: EServiceEvent): Uint8Array { @@ -253,6 +254,9 @@ export function catalogEventToBinaryDataV2(event: EServiceEventV2): Uint8Array { .with({ type: "EServiceSignalHubDisabled" }, ({ data }) => EServiceSignalHubDisabledV2.toBinary(data) ) + .with({ type: "EServicePersonalDataUpdatedAfterPublish" }, ({ data }) => + EServicePersonalDataUpdatedAfterPublishV2.toBinary(data) + ) .exhaustive(); } @@ -538,6 +542,11 @@ export const EServiceEventV2 = z.discriminatedUnion("type", [ type: z.literal("EServiceSignalHubDisabled"), data: protobufDecoder(EServiceSignalHubDisabledV2), }), + z.object({ + event_version: z.literal(2), + type: z.literal("EServicePersonalDataUpdatedAfterPublish"), + data: protobufDecoder(EServicePersonalDataUpdatedAfterPublishV2), + }), ]); export type EServiceEventV2 = z.infer; diff --git a/packages/notification-email-sender/src/index.ts b/packages/notification-email-sender/src/index.ts index c271a534ba..a35612c66b 100644 --- a/packages/notification-email-sender/src/index.ts +++ b/packages/notification-email-sender/src/index.ts @@ -150,7 +150,8 @@ export async function handleCatalogMessage( "EServiceDescriptorDocumentDeletedByTemplateUpdate", "EServiceDescriptorDocumentUpdatedByTemplateUpdate", "EServiceSignalHubEnabled", - "EServiceSignalHubDisabled" + "EServiceSignalHubDisabled", + "EServicePersonalDataUpdatedAfterPublish" ), }, () => { diff --git a/packages/notifier-seeder/src/models/catalog/catalogItemEventNotificationConverter.ts b/packages/notifier-seeder/src/models/catalog/catalogItemEventNotificationConverter.ts index f3c1c73856..d20b8386de 100644 --- a/packages/notifier-seeder/src/models/catalog/catalogItemEventNotificationConverter.ts +++ b/packages/notifier-seeder/src/models/catalog/catalogItemEventNotificationConverter.ts @@ -100,6 +100,7 @@ export const toCatalogItemEventNotification = ( { type: "EServiceSignalHubEnabled" }, // CatalogItemV1UpdatedV1 { type: "EServiceSignalHubDisabled" }, // CatalogItemV1UpdatedV1 { type: "EServiceNameUpdatedByTemplateUpdate" }, + { type: "EServicePersonalDataUpdatedAfterPublish" }, (e): CatalogItemNotification => ({ catalogItem: getCatalogItem(e), }) diff --git a/packages/notifier-seeder/src/models/catalog/catalogItemEventNotificationMessage.ts b/packages/notifier-seeder/src/models/catalog/catalogItemEventNotificationMessage.ts index 2920aabd9c..8d8207b251 100644 --- a/packages/notifier-seeder/src/models/catalog/catalogItemEventNotificationMessage.ts +++ b/packages/notifier-seeder/src/models/catalog/catalogItemEventNotificationMessage.ts @@ -21,6 +21,7 @@ export const eventV2TypeMapper = ( "EServiceDescriptionUpdatedByTemplateUpdate", "EServiceSignalHubEnabled", "EServiceSignalHubDisabled", + "EServicePersonalDataUpdatedAfterPublish", () => "catalog_item_updated" ) .with( From 72f466d5ed0dcbb528e4483db4d28e3d66d4ee99 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Tue, 9 Sep 2025 12:05:43 +0200 Subject: [PATCH 013/180] Implement endpoint --- packages/api-clients/open-api/catalogApi.yml | 64 +++++++++++++++++++ .../src/model/domain/errors.ts | 11 ++++ .../src/model/domain/toEvent.ts | 17 +++++ .../src/routers/EServiceRouter.ts | 34 +++++++++- .../src/services/catalogService.ts | 43 +++++++++++++ .../src/utilities/errorMappers.ts | 17 +++++ 6 files changed, 185 insertions(+), 1 deletion(-) diff --git a/packages/api-clients/open-api/catalogApi.yml b/packages/api-clients/open-api/catalogApi.yml index 5b39773647..0badca5123 100644 --- a/packages/api-clients/open-api/catalogApi.yml +++ b/packages/api-clients/open-api/catalogApi.yml @@ -1786,6 +1786,62 @@ paths: application/json: schema: $ref: "#/components/schemas/Problem" + /eservices/{eServiceId}/personalData: + parameters: + - $ref: "#/components/parameters/CorrelationIdHeader" + post: + security: + - bearerAuth: [] + tags: + - process + summary: Set personalData flag for published eservices + operationId: updateEServicePersonalDataAfterPublish + parameters: + - name: eServiceId + in: path + description: the eservice id + required: true + schema: + type: string + format: uuid + requestBody: + description: A payload containing a boolean that describes the personalData flag + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/EServicePersonalDataUpdateSeed" + responses: + "200": + description: EService personalData flag updated + content: + application/json: + schema: + $ref: "#/components/schemas/EService" + "400": + description: Bad request + content: + application/json: + schema: + $ref: "#/components/schemas/Problem" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: "#/components/schemas/Problem" + "404": + description: EService not found + content: + application/json: + schema: + $ref: "#/components/schemas/Problem" + "409": + description: Conflict + content: + application/json: + schema: + $ref: "#/components/schemas/Problem" /eservices/{eServiceId}/descriptors/{descriptorId}/approve: parameters: - $ref: "#/components/parameters/CorrelationIdHeader" @@ -3113,6 +3169,14 @@ components: type: boolean required: - isSignalHubEnabled + EServicePersonalDataUpdateSeed: + type: object + additionalProperties: false + properties: + personalData: + type: boolean + required: + - personalData EServiceDescriptor: type: object additionalProperties: false diff --git a/packages/catalog-process/src/model/domain/errors.ts b/packages/catalog-process/src/model/domain/errors.ts index e7368af48a..e4ef684996 100644 --- a/packages/catalog-process/src/model/domain/errors.ts +++ b/packages/catalog-process/src/model/domain/errors.ts @@ -52,6 +52,7 @@ export const errorCodes = { descriptorTemplateVersionNotFound: "0037", templateMissingRequiredRiskAnalysis: "0038", eserviceTemplateNameConflict: "0039", + eservicePersonalDataCanOnlyBeSetOnce: "0040", }; export type ErrorCodes = keyof typeof errorCodes; @@ -451,3 +452,13 @@ export function templateMissingRequiredRiskAnalysis( title: "Missing required risk analysis", }); } + +export function eservicePersonalDataCanOnlyBeSetOnce( + eserviceId: EServiceId +): ApiError { + return new ApiError({ + detail: `PersonalData flag has already been set for eService ${eserviceId}`, + code: "eservicePersonalDataCanOnlyBeSetOnce", + title: "EService personalData can only be set once", + }); +} diff --git a/packages/catalog-process/src/model/domain/toEvent.ts b/packages/catalog-process/src/model/domain/toEvent.ts index 3acaecd007..3b9e468278 100644 --- a/packages/catalog-process/src/model/domain/toEvent.ts +++ b/packages/catalog-process/src/model/domain/toEvent.ts @@ -856,3 +856,20 @@ export const toCreateEventEServiceSignalhubFlagDisabled = ( }, correlationId, }); + +export const toCreateEventEServicePersonalDataUpdatedAfterPublish = ( + version: number, + eservice: EService, + correlationId: CorrelationId +): CreateEvent => ({ + streamId: eservice.id, + version, + event: { + type: "EServicePersonalDataUpdatedAfterPublish", + event_version: 2, + data: { + eservice: toEServiceV2(eservice), + }, + }, + correlationId, +}); diff --git a/packages/catalog-process/src/routers/EServiceRouter.ts b/packages/catalog-process/src/routers/EServiceRouter.ts index e8b98bb175..4b5ac38316 100644 --- a/packages/catalog-process/src/routers/EServiceRouter.ts +++ b/packages/catalog-process/src/routers/EServiceRouter.ts @@ -73,8 +73,10 @@ import { updateTemplateInstanceDescriptorErrorMapper, updateAgreementApprovalPolicyErrorMapper, updateEServiceSignalhubFlagErrorMapper, + updateEServicePersonalDataErrorMapper, } from "../utilities/errorMappers.js"; import { CatalogService } from "../services/catalogService.js"; +import { config } from "../config/config.js"; const eservicesRouter = ( ctx: ZodiosContext, @@ -1336,7 +1338,37 @@ const eservicesRouter = ( return res.status(errorRes.status).send(errorRes); } } - ); + ) + .post("/eservices/:eServiceId/personalData", async (req, res) => { + const ctx = fromAppContext(req.ctx); + try { + validateAuthorization(ctx, [ADMIN_ROLE, API_ROLE]); + + if (config.featureFlagEservicePersonalData === false) { + return res.status(501); + } + + const updatedEService = + await catalogService.updateEServicePersonalDataAfterPublish( + unsafeBrandId(req.params.eServiceId), + req.body.personalData, + ctx + ); + + return res + .status(200) + .send( + catalogApi.EService.parse(eServiceToApiEService(updatedEService)) + ); + } catch (error) { + const errorRes = makeApiProblem( + error, + updateEServicePersonalDataErrorMapper, + ctx + ); + return res.status(errorRes.status).send(errorRes); + } + }); return eservicesRouter; }; diff --git a/packages/catalog-process/src/services/catalogService.ts b/packages/catalog-process/src/services/catalogService.ts index 013830e81d..76c252db2a 100644 --- a/packages/catalog-process/src/services/catalogService.ts +++ b/packages/catalog-process/src/services/catalogService.ts @@ -96,6 +96,7 @@ import { tenantNotFound, unchangedAttributes, templateMissingRequiredRiskAnalysis, + eservicePersonalDataCanOnlyBeSetOnce, } from "../model/domain/errors.js"; import { ApiGetEServicesFilters, Consumer } from "../model/domain/models.js"; import { @@ -140,6 +141,7 @@ import { toCreateEventEServiceUpdated, toCreateEventEServiceSignalhubFlagEnabled, toCreateEventEServiceSignalhubFlagDisabled, + toCreateEventEServicePersonalDataUpdatedAfterPublish, } from "../model/domain/toEvent.js"; import { getLatestDescriptor, @@ -3467,6 +3469,47 @@ export function catalogServiceBuilder( return updatedDescriptor; }, + async updateEServicePersonalDataAfterPublish( + eserviceId: EServiceId, + personalData: boolean, + { authData, correlationId, logger }: WithLogger> + ): Promise { + logger.info( + `Setting personalData flag for E-Service ${eserviceId} to ${personalData}` + ); + + const eservice = await retrieveEService(eserviceId, readModelService); + + await assertRequesterIsDelegateProducerOrProducer( + eservice.data.producerId, + eservice.data.id, + authData, + readModelService + ); + + assertEServiceNotTemplateInstance(eserviceId, eservice.data.templateId); + + assertEServiceUpdatableAfterPublish(eservice.data); + + if (eservice.data.personalData !== undefined) { + throw eservicePersonalDataCanOnlyBeSetOnce(eserviceId); + } + + const updatedEservice: EService = { + ...eservice.data, + personalData, + }; + + const event = toCreateEventEServicePersonalDataUpdatedAfterPublish( + eservice.metadata.version, + updatedEservice, + correlationId + ); + + await repository.createEvent(event); + + return updatedEservice; + }, }; } diff --git a/packages/catalog-process/src/utilities/errorMappers.ts b/packages/catalog-process/src/utilities/errorMappers.ts index 90c8cfd587..6897ef7905 100644 --- a/packages/catalog-process/src/utilities/errorMappers.ts +++ b/packages/catalog-process/src/utilities/errorMappers.ts @@ -671,3 +671,20 @@ export const updateTemplateInstanceDescriptorErrorMapper = ( () => HTTP_STATUS_BAD_REQUEST ) .otherwise(() => HTTP_STATUS_INTERNAL_SERVER_ERROR); + +export const updateEServicePersonalDataErrorMapper = ( + error: ApiError +): number => + match(error.code) + .with("eServiceNotFound", () => HTTP_STATUS_NOT_FOUND) + .with( + "operationForbidden", + "templateInstanceNotAllowed", + () => HTTP_STATUS_FORBIDDEN + ) + .with( + "eserviceWithoutValidDescriptors", + "eservicePersonalDataCanOnlyBeSetOnce", + () => HTTP_STATUS_CONFLICT + ) + .otherwise(() => HTTP_STATUS_INTERNAL_SERVER_ERROR); From e7fa5590246f4293a3388bdbfc1a9588c48c0a43 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Tue, 9 Sep 2025 17:17:16 +0200 Subject: [PATCH 014/180] Add bff endpoint --- packages/api-clients/open-api/bffApi.yml | 120 +++++++++++++++++- .../src/routers/catalogRouter.ts | 19 +++ .../src/services/catalogService.ts | 20 +++ 3 files changed, 158 insertions(+), 1 deletion(-) diff --git a/packages/api-clients/open-api/bffApi.yml b/packages/api-clients/open-api/bffApi.yml index 966a95e3f2..683ba811a9 100644 --- a/packages/api-clients/open-api/bffApi.yml +++ b/packages/api-clients/open-api/bffApi.yml @@ -5881,7 +5881,117 @@ paths: schema: type: integer description: Time interval in milliseconds. Allowed requests will be constantly replenished during the interval. At the end of the interval the max allowed requests will be available - + "403": + description: Forbidden + headers: + "X-Rate-Limit-Limit": + schema: + type: integer + description: Max allowed requests within time interval + "X-Rate-Limit-Remaining": + schema: + type: integer + description: Remaining requests within time interval + "X-Rate-Limit-Interval": + schema: + type: integer + description: Time interval in milliseconds. Allowed requests will be constantly replenished during the interval. At the end of the interval the max allowed requests will be available + content: + application/json: + schema: + $ref: "#/components/schemas/Problem" + "404": + description: EService not found + headers: + "X-Rate-Limit-Limit": + schema: + type: integer + description: Max allowed requests within time interval + "X-Rate-Limit-Remaining": + schema: + type: integer + description: Remaining requests within time interval + "X-Rate-Limit-Interval": + schema: + type: integer + description: Time interval in milliseconds. Allowed requests will be constantly replenished during the interval. At the end of the interval the max allowed requests will be available + content: + application/json: + schema: + $ref: "#/components/schemas/Problem" + "409": + description: Conflict + headers: + "X-Rate-Limit-Limit": + schema: + type: integer + description: Max allowed requests within time interval + "X-Rate-Limit-Remaining": + schema: + type: integer + description: Remaining requests within time interval + "X-Rate-Limit-Interval": + schema: + type: integer + description: Time interval in milliseconds. Allowed requests will be constantly replenished during the interval. At the end of the interval the max allowed requests will be available + content: + application/json: + schema: + $ref: "#/components/schemas/Problem" + /eservices/{eServiceId}/personalData: + post: + security: + - bearerAuth: [] + tags: + - eservices + summary: Set personalData flag for published eservices + operationId: updateEServicePersonalDataAfterPublish + parameters: + - name: eServiceId + in: path + description: the eservice id + required: true + schema: + type: string + format: uuid + requestBody: + description: A payload containing a boolean that describes the personalData flag + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/EServicePersonalDataUpdateSeed" + responses: + "204": + description: EService personalData flag updated + headers: + "X-Rate-Limit-Limit": + schema: + type: integer + description: Max allowed requests within time interval + "X-Rate-Limit-Remaining": + schema: + type: integer + description: Remaining requests within time interval + "X-Rate-Limit-Interval": + schema: + type: integer + description: Time interval in milliseconds. Allowed requests will be constantly replenished during the interval. At the end of the interval the max allowed requests will be available + "400": + description: Bad request + headers: + "X-Rate-Limit-Limit": + schema: + type: integer + description: Max allowed requests within time interval + "X-Rate-Limit-Remaining": + schema: + type: integer + description: Remaining requests within time interval + "X-Rate-Limit-Interval": + schema: + type: integer + description: Time interval in milliseconds. Allowed requests will be constantly replenished during the interval. At the end of the interval the max allowed requests will be available "403": description: Forbidden headers: @@ -21378,6 +21488,14 @@ components: type: boolean required: - isSignalHubEnabled + EServicePersonalDataUpdateSeed: + type: object + additionalProperties: false + properties: + personalData: + type: boolean + required: + - personalData RejectDelegatedEServiceDescriptorSeed: type: object additionalProperties: false diff --git a/packages/backend-for-frontend/src/routers/catalogRouter.ts b/packages/backend-for-frontend/src/routers/catalogRouter.ts index 6f07fbb6a3..9cc8445a74 100644 --- a/packages/backend-for-frontend/src/routers/catalogRouter.ts +++ b/packages/backend-for-frontend/src/routers/catalogRouter.ts @@ -734,6 +734,25 @@ const catalogRouter = ( return res.status(errorRes.status).send(errorRes); } }) + .post("/eservices/:eServiceId/personalData", async (req, res) => { + const ctx = fromBffAppContext(req.ctx, req.headers); + try { + await catalogService.updateEServicePersonalDataFlag( + ctx, + unsafeBrandId(req.params.eServiceId), + req.body + ); + return res.status(204).send(); + } catch (error) { + const errorRes = makeApiProblem( + error, + emptyErrorMapper, + ctx, + `Error setting personalData flag for eservice with Id: ${req.params.eServiceId}` + ); + return res.status(errorRes.status).send(errorRes); + } + }) .get( "/eservices/:eServiceId/riskAnalysis/:riskAnalysisId", async (req, res) => { diff --git a/packages/backend-for-frontend/src/services/catalogService.ts b/packages/backend-for-frontend/src/services/catalogService.ts index 9a038e3d84..f24ab3f32a 100644 --- a/packages/backend-for-frontend/src/services/catalogService.ts +++ b/packages/backend-for-frontend/src/services/catalogService.ts @@ -597,6 +597,26 @@ export function catalogServiceBuilder( } ); }, + + updateEServicePersonalDataFlag: async ( + { headers, logger }: WithLogger, + eServiceId: EServiceId, + personalDataSeed: bffApi.EServicePersonalDataUpdateSeed + ): Promise => { + logger.info( + `Set personal flag for E-Service with id = ${eServiceId} to ${personalDataSeed.personalData}` + ); + await catalogProcessClient.updateEServicePersonalDataAfterPublish( + personalDataSeed, + { + headers, + params: { + eServiceId, + }, + } + ); + }, + createEService: async ( eServiceSeed: bffApi.EServiceSeed, { headers, logger }: WithLogger From 8070d2822a1fa1e6acbef3d51245b395b5ae99c3 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Wed, 10 Sep 2025 14:30:29 +0200 Subject: [PATCH 015/180] Fix tests --- .../test/integration/patchUpdatePurpose.test.ts | 6 ++++-- packages/purpose-process/test/mockUtils.ts | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/purpose-process/test/integration/patchUpdatePurpose.test.ts b/packages/purpose-process/test/integration/patchUpdatePurpose.test.ts index bf834f3ace..6cb081d765 100644 --- a/packages/purpose-process/test/integration/patchUpdatePurpose.test.ts +++ b/packages/purpose-process/test/integration/patchUpdatePurpose.test.ts @@ -33,7 +33,7 @@ import { } from "pagopa-interop-models"; import { purposeApi } from "pagopa-interop-api-clients"; import { describe, it, expect, beforeAll, vi, afterAll } from "vitest"; -import { unexpectedRulesVersionError } from "pagopa-interop-commons"; +import { rulesVersionNotFoundError } from "pagopa-interop-commons"; import { addOnePurpose, readLastPurposeEvent, @@ -653,7 +653,9 @@ describe("patchUpdatePurpose", () => { }) ) ).rejects.toThrowError( - riskAnalysisValidationFailed([unexpectedRulesVersionError("0")]) + riskAnalysisValidationFailed([ + rulesVersionNotFoundError(consumer.kind!, "0"), + ]) ); }); }); diff --git a/packages/purpose-process/test/mockUtils.ts b/packages/purpose-process/test/mockUtils.ts index 97a6ddd12a..455f975270 100644 --- a/packages/purpose-process/test/mockUtils.ts +++ b/packages/purpose-process/test/mockUtils.ts @@ -91,7 +91,8 @@ export const createUpdatedPurpose = ( validateAndTransformRiskAnalysis( purposeUpdateContent.riskAnalysisForm, false, - tenantKind + tenantKind, + new Date() )!, writtenRiskAnalysisForm ), From 380464cbc715a6bbc9f29de4d9e28ddacbb0de73 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Wed, 10 Sep 2025 16:01:04 +0200 Subject: [PATCH 016/180] Fix logic --- packages/purpose-process/src/services/purposeService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/purpose-process/src/services/purposeService.ts b/packages/purpose-process/src/services/purposeService.ts index c36c17619f..c8f0af9d3d 100644 --- a/packages/purpose-process/src/services/purposeService.ts +++ b/packages/purpose-process/src/services/purposeService.ts @@ -1675,7 +1675,7 @@ const performUpdatePurpose = async ( ); const newRiskAnalysis: PurposeRiskAnalysisForm | undefined = - mode === eserviceMode.deliver + mode === eserviceMode.deliver && riskAnalysisForm ? validateAndTransformRiskAnalysis( riskAnalysisForm, true, From f134dabaab1e00c023725d8a3ca3647643d9a3b4 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Wed, 10 Sep 2025 17:11:05 +0200 Subject: [PATCH 017/180] Improve error --- packages/commons/src/risk-analysis/riskAnalysisValidation.ts | 4 +++- .../src/risk-analysis/riskAnalysisValidationErrors.ts | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/commons/src/risk-analysis/riskAnalysisValidation.ts b/packages/commons/src/risk-analysis/riskAnalysisValidation.ts index a5a90b0608..1f8c1f2f90 100644 --- a/packages/commons/src/risk-analysis/riskAnalysisValidation.ts +++ b/packages/commons/src/risk-analysis/riskAnalysisValidation.ts @@ -48,7 +48,9 @@ export function validateRiskAnalysis( formRulesForValidation.expiration && formRulesForValidation.expiration < dateForValidation ) { - return invalidResult([expiredRulesVersionError(riskAnalysisForm.version)]); + return invalidResult([ + expiredRulesVersionError(riskAnalysisForm.version, tenantKind), + ]); } const validationRules = buildValidationRules(formRulesForValidation); diff --git a/packages/commons/src/risk-analysis/riskAnalysisValidationErrors.ts b/packages/commons/src/risk-analysis/riskAnalysisValidationErrors.ts index de900d702f..97349222f4 100644 --- a/packages/commons/src/risk-analysis/riskAnalysisValidationErrors.ts +++ b/packages/commons/src/risk-analysis/riskAnalysisValidationErrors.ts @@ -33,11 +33,12 @@ export function rulesVersionNotFoundError( } export function expiredRulesVersionError( - version: string + version: string, + tenantKind: TenantKind ): RiskAnalysisValidationIssue { return new RiskAnalysisValidationIssue({ code: "expiredRulesVersionError", - detail: `Expired ruleset version ${version}`, + detail: `Ruleset version ${version} for tenant kind ${tenantKind} has expired`, }); } From 9026d1f57c8da3dc003926428bb528cbbc785d34 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Wed, 10 Sep 2025 17:11:14 +0200 Subject: [PATCH 018/180] Update tests --- .../integration/createRiskAnalysis.test.ts | 44 ++++++++++++++ .../commons-test/src/riskAnalysisTestUtils.ts | 60 +++++++++++++++++++ ...riskAnalysisValidation.integration.test.ts | 33 +++++++++- 3 files changed, 136 insertions(+), 1 deletion(-) diff --git a/packages/catalog-process/test/integration/createRiskAnalysis.test.ts b/packages/catalog-process/test/integration/createRiskAnalysis.test.ts index 02f8fb22da..0539ea1c30 100644 --- a/packages/catalog-process/test/integration/createRiskAnalysis.test.ts +++ b/packages/catalog-process/test/integration/createRiskAnalysis.test.ts @@ -3,6 +3,7 @@ import { unexpectedFieldValueError, unexpectedFieldError, + expiredRulesVersionError, } from "pagopa-interop-commons"; import { randomArrayItem, @@ -14,6 +15,7 @@ import { getMockAuthData, getMockDescriptor, getMockEService, + getMockExpiredRiskAnalysisPA, } from "pagopa-interop-commons-test"; import { TenantKind, @@ -494,6 +496,48 @@ describe("create risk analysis", () => { ]) ); }); + it("should throw riskAnalysisValidationFailed if the risk analysis rules version has expired", async () => { + const producer: Tenant = { + ...getMockTenant(), + kind: tenantKind.PA, + }; + + const mockValidRiskAnalysis = getMockExpiredRiskAnalysisPA(); + + const riskAnalysisSeed: catalogApi.EServiceRiskAnalysisSeed = { + ...buildRiskAnalysisSeed(mockValidRiskAnalysis), + }; + + const eservice: EService = { + ...mockEService, + producerId: producer.id, + mode: eserviceMode.receive, + descriptors: [ + { + ...mockDescriptor, + state: descriptorState.draft, + }, + ], + }; + + await addOneTenant(producer); + await addOneEService(eservice); + + expect( + catalogService.createRiskAnalysis( + eservice.id, + riskAnalysisSeed, + getMockContext({ authData: getMockAuthData(producer.id) }) + ) + ).rejects.toThrowError( + riskAnalysisValidationFailed([ + expiredRulesVersionError( + riskAnalysisSeed.riskAnalysisForm.version, + tenantKind.PA + ), + ]) + ); + }); it("should throw templateInstanceNotAllowed if the templateId is defined", async () => { const templateId = unsafeBrandId(generateId()); const producerTenantKind: TenantKind = randomArrayItem( diff --git a/packages/commons-test/src/riskAnalysisTestUtils.ts b/packages/commons-test/src/riskAnalysisTestUtils.ts index 24f035c440..5363849691 100644 --- a/packages/commons-test/src/riskAnalysisTestUtils.ts +++ b/packages/commons-test/src/riskAnalysisTestUtils.ts @@ -15,6 +15,31 @@ import { import { match } from "ts-pattern"; import { z } from "zod"; +export const expiredRiskAnalysis2_0_Pa: RiskAnalysisFormToValidate = { + version: "2.0", + answers: { + purpose: ["INSTITUTIONAL"], + institutionalPurpose: ["MyPurpose"], + personalDataTypes: ["WITH_NON_IDENTIFYING_DATA"], + legalBasis: ["LEGAL_OBLIGATION"], + legalObligationReference: ["somethingLegal"], + legalBasisPublicInterest: ["RULE_OF_LAW"], + ruleOfLawText: ["TheLaw"], + knowsDataQuantity: ["NO"], + deliveryMethod: ["ANONYMOUS"], + policyProvided: ["NO"], + reasonPolicyNotProvided: ["Test"], + confirmPricipleIntegrityAndDiscretion: ["true"], + doneDpia: ["NO"], + dataDownload: ["YES"], + dataRetentionPeriod: ["true"], + purposePursuit: ["MERE_CORRECTNESS"], + checkedExistenceMereCorrectnessInteropCatalogue: ["true"], + usesThirdPartyData: ["NO"], + declarationConfirmGDPR: ["true"], + }, +}; + export const validRiskAnalysis3_0_Pa: RiskAnalysisFormToValidate = { version: "3.0", answers: { @@ -42,6 +67,35 @@ export const validRiskAnalysis3_0_Pa: RiskAnalysisFormToValidate = { }, }; +export const validatedExpiredRiskAnalysis2_0_Pa: RiskAnalysisValidatedForm = { + version: "2.0", + singleAnswers: [ + { key: "purpose", value: "INSTITUTIONAL" }, + { key: "institutionalPurpose", value: "MyPurpose" }, + { key: "personalDataTypes", value: "WITH_NON_IDENTIFYING_DATA" }, + { key: "legalBasis", value: "LEGAL_OBLIGATION" }, + { key: "legalObligationReference", value: "somethingLegal" }, + { key: "legalBasisPublicInterest", value: "RULE_OF_LAW" }, + { key: "ruleOfLawText", value: "TheLaw" }, + { key: "knowsDataQuantity", value: "NO" }, + { key: "deliveryMethod", value: "ANONYMOUS" }, + { key: "policyProvided", value: "NO" }, + { key: "reasonPolicyNotProvided", value: "Test" }, + { key: "confirmPricipleIntegrityAndDiscretion", value: "true" }, + { key: "doneDpia", value: "NO" }, + { key: "dataDownload", value: "YES" }, + { key: "dataRetentionPeriod", value: "true" }, + { key: "purposePursuit", value: "MERE_CORRECTNESS" }, + { + key: "checkedExistenceMereCorrectnessInteropCatalogue", + value: "true", + }, + { key: "usesThirdPartyData", value: "NO" }, + { key: "declarationConfirmGDPR", value: "true" }, + ], + multiAnswers: [], +}; + export const validatedRiskAnalysis3_0_Pa: RiskAnalysisValidatedForm = { version: validRiskAnalysis3_0_Pa.version, singleAnswers: [ @@ -167,6 +221,12 @@ export const getMockValidRiskAnalysis = ( ) .exhaustive(); +export const getMockExpiredRiskAnalysisPA = (): RiskAnalysis => + riskAnalysisValidatedFormToNewRiskAnalysis( + validatedExpiredRiskAnalysis2_0_Pa, + generateMock(z.string()) + ); + export const getMockValidEServiceTemplateRiskAnalysis = ( producerTenantKind: TenantKind ): EServiceTemplateRiskAnalysis => ({ diff --git a/packages/commons-test/test/riskAnalysisValidation.integration.test.ts b/packages/commons-test/test/riskAnalysisValidation.integration.test.ts index a144b13a62..c3735dae96 100644 --- a/packages/commons-test/test/riskAnalysisValidation.integration.test.ts +++ b/packages/commons-test/test/riskAnalysisValidation.integration.test.ts @@ -10,8 +10,11 @@ import { unexpectedFieldValueError, validateRiskAnalysis, rulesVersionNotFoundError, + expiredRulesVersionError, } from "pagopa-interop-commons"; +import { tenantKind } from "pagopa-interop-models"; import { + expiredRiskAnalysis2_0_Pa, validRiskAnalysis2_0_Private, validRiskAnalysis3_0_Pa, validSchemaOnlyRiskAnalysis2_0_Private, @@ -171,7 +174,35 @@ describe("Risk Analysis Validation", () => { }); }); - it("fail if a provided answer depends on missing fields", () => { + it("should fail if version has expired", () => { + const expiredVersionForPA = "2.0"; + const expiredRiskAnalysis: RiskAnalysisFormToValidate = { + ...expiredRiskAnalysis2_0_Pa, + version: expiredVersionForPA, + }; + + expect( + validateRiskAnalysis(expiredRiskAnalysis, false, "PA", new Date()) + ).toEqual({ + type: "invalid", + issues: [expiredRulesVersionError(expiredVersionForPA, tenantKind.PA)], + }); + + const invalidVersionForPrivate = "not a valid version"; + const invalidRiskAnalysis2: RiskAnalysisFormToValidate = { + ...validRiskAnalysis2_0_Private, + version: invalidVersionForPrivate, + }; + + expect( + validateRiskAnalysis(invalidRiskAnalysis2, false, "PRIVATE", new Date()) + ).toEqual({ + type: "invalid", + issues: [rulesVersionNotFoundError("PRIVATE", invalidVersionForPrivate)], + }); + }); + + it("should fail if a provided answer depends on missing fields", () => { const riskAnalysis: RiskAnalysisFormToValidate = { version: validRiskAnalysis3_0_Pa.version, answers: { From a14a316b278b0de7996918921adadca301e759ad Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Wed, 10 Sep 2025 17:44:13 +0200 Subject: [PATCH 019/180] Update tests --- .../integration/createRiskAnalysis.test.ts | 10 ++- .../commons-test/src/riskAnalysisTestUtils.ts | 79 +++++++++++++++++-- ...riskAnalysisValidation.integration.test.ts | 13 +-- 3 files changed, 88 insertions(+), 14 deletions(-) diff --git a/packages/catalog-process/test/integration/createRiskAnalysis.test.ts b/packages/catalog-process/test/integration/createRiskAnalysis.test.ts index 0539ea1c30..ffbf5364c5 100644 --- a/packages/catalog-process/test/integration/createRiskAnalysis.test.ts +++ b/packages/catalog-process/test/integration/createRiskAnalysis.test.ts @@ -15,7 +15,7 @@ import { getMockAuthData, getMockDescriptor, getMockEService, - getMockExpiredRiskAnalysisPA, + getMockExpiredRiskAnalysis, } from "pagopa-interop-commons-test"; import { TenantKind, @@ -497,12 +497,16 @@ describe("create risk analysis", () => { ); }); it("should throw riskAnalysisValidationFailed if the risk analysis rules version has expired", async () => { + const producerTenantKind: TenantKind = randomArrayItem( + Object.values(tenantKind) + ); const producer: Tenant = { ...getMockTenant(), - kind: tenantKind.PA, + kind: producerTenantKind, }; - const mockValidRiskAnalysis = getMockExpiredRiskAnalysisPA(); + const mockValidRiskAnalysis = + getMockExpiredRiskAnalysis(producerTenantKind); const riskAnalysisSeed: catalogApi.EServiceRiskAnalysisSeed = { ...buildRiskAnalysisSeed(mockValidRiskAnalysis), diff --git a/packages/commons-test/src/riskAnalysisTestUtils.ts b/packages/commons-test/src/riskAnalysisTestUtils.ts index 5363849691..a2826f167e 100644 --- a/packages/commons-test/src/riskAnalysisTestUtils.ts +++ b/packages/commons-test/src/riskAnalysisTestUtils.ts @@ -127,6 +127,32 @@ export const validatedRiskAnalysis3_0_Pa: RiskAnalysisValidatedForm = { ], }; +export const validRiskAnalysis1_0_Private: RiskAnalysisFormToValidate = { + version: "1.0", + answers: { + purpose: ["INSTITUTIONAL"], + institutionalPurpose: ["MyPurpose"], + usesPersonalData: ["YES"], + personalDataTypes: ["OTHER"], + otherPersonalDataTypes: ["MyDataTypes"], + legalBasis: ["LEGAL_OBLIGATION", "PUBLIC_INTEREST"], + legalObligationReference: ["YES"], + legalBasisPublicInterest: ["RULE_OF_LAW"], + ruleOfLawText: ["TheLaw"], + knowsDataQuantity: ["NO"], + dataDownload: ["YES"], + deliveryMethod: ["CLEARTEXT"], + policyProvided: ["NO"], + confirmPricipleIntegrityAndDiscretion: ["true"], + reasonPolicyNotProvided: ["Test"], + doneDpia: ["NO"], + dataRetentionPeriod: ["10"], + purposePursuit: ["MERE_CORRECTNESS"], + checkedExistenceMereCorrectnessInteropCatalogue: ["true"], + declarationConfirmGDPR: ["true"], + }, +}; + export const validRiskAnalysis2_0_Private: RiskAnalysisFormToValidate = { version: "2.0", answers: { @@ -154,6 +180,37 @@ export const validRiskAnalysis2_0_Private: RiskAnalysisFormToValidate = { }, }; +export const validatedRiskAnalysis1_0_Private: RiskAnalysisValidatedForm = { + version: validRiskAnalysis1_0_Private.version, + singleAnswers: [ + { key: "purpose", value: "INSTITUTIONAL" }, + { key: "institutionalPurpose", value: "MyPurpose" }, + { key: "usesPersonalData", value: "YES" }, + { key: "otherPersonalDataTypes", value: "MyDataTypes" }, + { key: "legalObligationReference", value: "YES" }, + { key: "legalBasisPublicInterest", value: "RULE_OF_LAW" }, + { key: "ruleOfLawText", value: "TheLaw" }, + { key: "knowsDataQuantity", value: "NO" }, + { key: "dataDownload", value: "YES" }, + { key: "deliveryMethod", value: "CLEARTEXT" }, + { key: "policyProvided", value: "NO" }, + { key: "confirmPricipleIntegrityAndDiscretion", value: "true" }, + { key: "reasonPolicyNotProvided", value: "Test" }, + { key: "doneDpia", value: "NO" }, + { key: "dataRetentionPeriod", value: "10" }, + { key: "purposePursuit", value: "MERE_CORRECTNESS" }, + { + key: "checkedExistenceMereCorrectnessInteropCatalogue", + value: "true", + }, + { key: "declarationConfirmGDPR", value: "true" }, + ], + multiAnswers: [ + { key: "personalDataTypes", values: ["OTHER"] }, + { key: "legalBasis", values: ["LEGAL_OBLIGATION", "PUBLIC_INTEREST"] }, + ], +}; + export const validatedRiskAnalysis2_0_Private: RiskAnalysisValidatedForm = { version: validRiskAnalysis2_0_Private.version, singleAnswers: [ @@ -221,11 +278,23 @@ export const getMockValidRiskAnalysis = ( ) .exhaustive(); -export const getMockExpiredRiskAnalysisPA = (): RiskAnalysis => - riskAnalysisValidatedFormToNewRiskAnalysis( - validatedExpiredRiskAnalysis2_0_Pa, - generateMock(z.string()) - ); +export const getMockExpiredRiskAnalysis = ( + producerTenantKind: TenantKind +): RiskAnalysis => + match(producerTenantKind) + .with(tenantKind.PA, () => + riskAnalysisValidatedFormToNewRiskAnalysis( + validatedExpiredRiskAnalysis2_0_Pa, + generateMock(z.string()) + ) + ) + .with(tenantKind.PRIVATE, tenantKind.GSP, tenantKind.SCP, () => + riskAnalysisValidatedFormToNewRiskAnalysis( + validatedRiskAnalysis1_0_Private, + generateMock(z.string()) + ) + ) + .exhaustive(); export const getMockValidEServiceTemplateRiskAnalysis = ( producerTenantKind: TenantKind diff --git a/packages/commons-test/test/riskAnalysisValidation.integration.test.ts b/packages/commons-test/test/riskAnalysisValidation.integration.test.ts index c3735dae96..20a32364e8 100644 --- a/packages/commons-test/test/riskAnalysisValidation.integration.test.ts +++ b/packages/commons-test/test/riskAnalysisValidation.integration.test.ts @@ -15,6 +15,7 @@ import { import { tenantKind } from "pagopa-interop-models"; import { expiredRiskAnalysis2_0_Pa, + validRiskAnalysis1_0_Private, validRiskAnalysis2_0_Private, validRiskAnalysis3_0_Pa, validSchemaOnlyRiskAnalysis2_0_Private, @@ -188,17 +189,17 @@ describe("Risk Analysis Validation", () => { issues: [expiredRulesVersionError(expiredVersionForPA, tenantKind.PA)], }); - const invalidVersionForPrivate = "not a valid version"; - const invalidRiskAnalysis2: RiskAnalysisFormToValidate = { - ...validRiskAnalysis2_0_Private, - version: invalidVersionForPrivate, + const expiredVersionForPrivate = "1.0"; + const expiredRiskAnalysis2: RiskAnalysisFormToValidate = { + ...validRiskAnalysis1_0_Private, + version: expiredVersionForPrivate, }; expect( - validateRiskAnalysis(invalidRiskAnalysis2, false, "PRIVATE", new Date()) + validateRiskAnalysis(expiredRiskAnalysis2, false, "PRIVATE", new Date()) ).toEqual({ type: "invalid", - issues: [rulesVersionNotFoundError("PRIVATE", invalidVersionForPrivate)], + issues: [expiredRulesVersionError(expiredVersionForPrivate, "PRIVATE")], }); }); From 538bf6b1c4f2c878a97a95db632235a121964bda Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 11 Sep 2025 12:11:03 +0200 Subject: [PATCH 020/180] Add test --- .../commons-test/src/riskAnalysisTestUtils.ts | 16 +++++++++ .../test/integration/createPurpose.test.ts | 35 ++++++++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/packages/commons-test/src/riskAnalysisTestUtils.ts b/packages/commons-test/src/riskAnalysisTestUtils.ts index a2826f167e..0b49eadc0d 100644 --- a/packages/commons-test/src/riskAnalysisTestUtils.ts +++ b/packages/commons-test/src/riskAnalysisTestUtils.ts @@ -303,6 +303,22 @@ export const getMockValidEServiceTemplateRiskAnalysis = ( tenantKind: producerTenantKind, }); +export const getMockExpiredRiskAnalysisForm = ( + producerTenantKind: TenantKind +): RiskAnalysisForm => + match(producerTenantKind) + .with(tenantKind.PA, () => + riskAnalysisValidatedFormToNewRiskAnalysisForm( + validatedExpiredRiskAnalysis2_0_Pa + ) + ) + .with(tenantKind.PRIVATE, tenantKind.GSP, tenantKind.SCP, () => + riskAnalysisValidatedFormToNewRiskAnalysisForm( + validatedRiskAnalysis1_0_Private + ) + ) + .exhaustive(); + export const getMockValidRiskAnalysisForm = ( producerTenantKind: TenantKind ): RiskAnalysisForm => diff --git a/packages/purpose-process/test/integration/createPurpose.test.ts b/packages/purpose-process/test/integration/createPurpose.test.ts index 6fafcb11d8..53c112e504 100644 --- a/packages/purpose-process/test/integration/createPurpose.test.ts +++ b/packages/purpose-process/test/integration/createPurpose.test.ts @@ -34,8 +34,12 @@ import { getMockAuthData, getMockDelegation, getMockContext, + getMockExpiredRiskAnalysisForm, } from "pagopa-interop-commons-test"; -import { rulesVersionNotFoundError } from "pagopa-interop-commons"; +import { + expiredRulesVersionError, + rulesVersionNotFoundError, +} from "pagopa-interop-commons"; import { missingFreeOfChargeReason, tenantKindNotFound, @@ -81,6 +85,9 @@ describe("createPurpose", () => { ); const mockValidRiskAnalysisForm = getMockValidRiskAnalysisForm(tenantKind.PA); + const mockExpiredRiskAnalysisForm = getMockExpiredRiskAnalysisForm( + tenantKind.PA + ); const purposeSeed = getMockPurposeSeed( eService1.id, @@ -578,6 +585,32 @@ describe("createPurpose", () => { ]) ); }); + it("should throw riskAnalysisValidationFailed if the purpose has an expired risk analysis ", async () => { + await addOneTenant(tenant); + await addOneAgreement(agreementEservice1); + await addOneEService(eService1); + + const seed: purposeApi.PurposeSeed = { + ...purposeSeed, + riskAnalysisForm: buildRiskAnalysisFormSeed(mockExpiredRiskAnalysisForm), + }; + + expect( + purposeService.createPurpose( + seed, + getMockContext({ + authData: getMockAuthData(unsafeBrandId(seed.consumerId)), + }) + ) + ).rejects.toThrowError( + riskAnalysisValidationFailed([ + expiredRulesVersionError( + mockExpiredRiskAnalysisForm.version, + tenant.kind! + ), + ]) + ); + }); it("should throw duplicatedPurposeName if a purpose with same name already exists", async () => { const existingPurpose: Purpose = { ...getMockPurpose(), From fcd5fcc54a5e5af5abdb28f341fb3d8aba75ec77 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 11 Sep 2025 12:28:20 +0200 Subject: [PATCH 021/180] Add test --- .../commons-test/src/riskAnalysisTestUtils.ts | 13 +++-- ...createEServiceTemplateRiskAnalysis.test.ts | 50 +++++++++++++++++++ 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/packages/commons-test/src/riskAnalysisTestUtils.ts b/packages/commons-test/src/riskAnalysisTestUtils.ts index 0b49eadc0d..f94f8c1633 100644 --- a/packages/commons-test/src/riskAnalysisTestUtils.ts +++ b/packages/commons-test/src/riskAnalysisTestUtils.ts @@ -67,7 +67,7 @@ export const validRiskAnalysis3_0_Pa: RiskAnalysisFormToValidate = { }, }; -export const validatedExpiredRiskAnalysis2_0_Pa: RiskAnalysisValidatedForm = { +export const validatedRiskAnalysis2_0_Pa: RiskAnalysisValidatedForm = { version: "2.0", singleAnswers: [ { key: "purpose", value: "INSTITUTIONAL" }, @@ -284,7 +284,7 @@ export const getMockExpiredRiskAnalysis = ( match(producerTenantKind) .with(tenantKind.PA, () => riskAnalysisValidatedFormToNewRiskAnalysis( - validatedExpiredRiskAnalysis2_0_Pa, + validatedRiskAnalysis2_0_Pa, generateMock(z.string()) ) ) @@ -303,13 +303,20 @@ export const getMockValidEServiceTemplateRiskAnalysis = ( tenantKind: producerTenantKind, }); +export const getMockExpiredEServiceTemplateRiskAnalysis = ( + producerTenantKind: TenantKind +): EServiceTemplateRiskAnalysis => ({ + ...getMockExpiredRiskAnalysis(producerTenantKind), + tenantKind: producerTenantKind, +}); + export const getMockExpiredRiskAnalysisForm = ( producerTenantKind: TenantKind ): RiskAnalysisForm => match(producerTenantKind) .with(tenantKind.PA, () => riskAnalysisValidatedFormToNewRiskAnalysisForm( - validatedExpiredRiskAnalysis2_0_Pa + validatedRiskAnalysis2_0_Pa ) ) .with(tenantKind.PRIVATE, tenantKind.GSP, tenantKind.SCP, () => diff --git a/packages/eservice-template-process/test/integration/createEServiceTemplateRiskAnalysis.test.ts b/packages/eservice-template-process/test/integration/createEServiceTemplateRiskAnalysis.test.ts index a9385ad74c..f2084a8bc3 100644 --- a/packages/eservice-template-process/test/integration/createEServiceTemplateRiskAnalysis.test.ts +++ b/packages/eservice-template-process/test/integration/createEServiceTemplateRiskAnalysis.test.ts @@ -1,6 +1,7 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable @typescript-eslint/no-floating-promises */ import { + expiredRulesVersionError, unexpectedFieldError, unexpectedFieldValueError, } from "pagopa-interop-commons"; @@ -14,6 +15,7 @@ import { getMockValidEServiceTemplateRiskAnalysis, randomArrayItem, getMockContext, + getMockExpiredEServiceTemplateRiskAnalysis, } from "pagopa-interop-commons-test"; import { generateId, @@ -375,4 +377,52 @@ describe("createEServiceTemplateRiskAnalysis", () => { ]) ); }); + it("should throw riskAnalysisValidationFailed if the risk analysis version has expired", async () => { + const requesterId = generateId(); + + const creatorTenantKind: TenantKind = randomArrayItem( + Object.values(tenantKind) + ); + const creator: Tenant = { + ...getMockTenant(requesterId), + kind: creatorTenantKind, + }; + + const eserviceTemplateVersion: EServiceTemplateVersion = { + ...getMockEServiceTemplateVersion(), + state: eserviceTemplateVersionState.draft, + interface: getMockDocument(), + }; + const eserviceTemplate: EServiceTemplate = { + ...getMockEServiceTemplate(), + mode: eserviceMode.receive, + versions: [eserviceTemplateVersion], + creatorId: requesterId, + }; + await addOneTenant(creator); + await addOneEServiceTemplate(eserviceTemplate); + + const mockExpiredRiskAnalysis = + getMockExpiredEServiceTemplateRiskAnalysis(creatorTenantKind); + const riskAnalysisSeed: eserviceTemplateApi.EServiceTemplateRiskAnalysisSeed = + buildRiskAnalysisSeed(mockExpiredRiskAnalysis); + + expect( + eserviceTemplateService.createRiskAnalysis( + eserviceTemplate.id, + riskAnalysisSeed, + getMockContext({ + authData: getMockAuthData(eserviceTemplate.creatorId), + }) + ) + ).rejects.toThrowError( + riskAnalysisValidationFailed([ + expiredRulesVersionError( + riskAnalysisSeed.riskAnalysisForm.version, + creatorTenantKind + ), + unexpectedFieldError("unexpectedField"), + ]) + ); + }); }); From 1a5123c905c046b075c757a9bee933245f5b73e5 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 11 Sep 2025 14:24:50 +0200 Subject: [PATCH 022/180] Fix test --- .../catalog-process/test/integration/createRiskAnalysis.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/catalog-process/test/integration/createRiskAnalysis.test.ts b/packages/catalog-process/test/integration/createRiskAnalysis.test.ts index ffbf5364c5..938c1f3494 100644 --- a/packages/catalog-process/test/integration/createRiskAnalysis.test.ts +++ b/packages/catalog-process/test/integration/createRiskAnalysis.test.ts @@ -537,7 +537,7 @@ describe("create risk analysis", () => { riskAnalysisValidationFailed([ expiredRulesVersionError( riskAnalysisSeed.riskAnalysisForm.version, - tenantKind.PA + producerTenantKind ), ]) ); From 29afe270ffed039060ecae1bdbceec3b886ee0f7 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 11 Sep 2025 15:02:50 +0200 Subject: [PATCH 023/180] Fix test --- .../test/integration/createEServiceTemplateRiskAnalysis.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/eservice-template-process/test/integration/createEServiceTemplateRiskAnalysis.test.ts b/packages/eservice-template-process/test/integration/createEServiceTemplateRiskAnalysis.test.ts index f2084a8bc3..260ccc9dc5 100644 --- a/packages/eservice-template-process/test/integration/createEServiceTemplateRiskAnalysis.test.ts +++ b/packages/eservice-template-process/test/integration/createEServiceTemplateRiskAnalysis.test.ts @@ -421,7 +421,6 @@ describe("createEServiceTemplateRiskAnalysis", () => { riskAnalysisSeed.riskAnalysisForm.version, creatorTenantKind ), - unexpectedFieldError("unexpectedField"), ]) ); }); From b79f5d1674e027a47c0412f03b81a73aefd6534c Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 11 Sep 2025 16:08:34 +0200 Subject: [PATCH 024/180] Update api spec --- packages/api-clients/open-api/bffApi.yml | 2 ++ packages/api-clients/open-api/catalogApi.yml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/packages/api-clients/open-api/bffApi.yml b/packages/api-clients/open-api/bffApi.yml index ccda758f47..81f96b35b2 100644 --- a/packages/api-clients/open-api/bffApi.yml +++ b/packages/api-clients/open-api/bffApi.yml @@ -21193,6 +21193,8 @@ components: type: boolean isClientAccessDelegable: type: boolean + personalData: + type: boolean UpdateEServiceTemplateInstanceSeed: type: object additionalProperties: false diff --git a/packages/api-clients/open-api/catalogApi.yml b/packages/api-clients/open-api/catalogApi.yml index 599c6b283c..f8e8f4c139 100644 --- a/packages/api-clients/open-api/catalogApi.yml +++ b/packages/api-clients/open-api/catalogApi.yml @@ -2662,6 +2662,8 @@ components: type: boolean isClientAccessDelegable: type: boolean + personalData: + type: boolean UpdateEServiceTemplateInstanceSeed: type: object additionalProperties: false From 0ef42b7600db6271746e48c3598705ec2b971181 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 11 Sep 2025 16:08:59 +0200 Subject: [PATCH 025/180] Set personalData in updateDraftEService --- packages/catalog-process/src/services/catalogService.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/catalog-process/src/services/catalogService.ts b/packages/catalog-process/src/services/catalogService.ts index 9cc88cd8ba..8f8388ca59 100644 --- a/packages/catalog-process/src/services/catalogService.ts +++ b/packages/catalog-process/src/services/catalogService.ts @@ -3967,6 +3967,11 @@ async function updateDraftEService( ) .exhaustive(); + const updatedPersonalData = match(type) + .with("put", () => personalData) + .with("patch", () => personalData ?? eservice.data.personalData) + .exhaustive(); + const updatedEService: EService = { ...eservice.data, description: description ?? eservice.data.description, @@ -3996,6 +4001,7 @@ async function updateDraftEService( .with(false, () => false) .with(true, () => updatedIsClientAccessDelegable) .exhaustive(), + personalData: updatedPersonalData, }; const event = await repository.createEvent( From 156c3e1bdf5fa2a2d7cfa74990b275785fe50a57 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 11 Sep 2025 16:09:05 +0200 Subject: [PATCH 026/180] Update test --- .../catalog-process/test/integration/createEService.test.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/catalog-process/test/integration/createEService.test.ts b/packages/catalog-process/test/integration/createEService.test.ts index 73afca62a3..7e474f397d 100644 --- a/packages/catalog-process/test/integration/createEService.test.ts +++ b/packages/catalog-process/test/integration/createEService.test.ts @@ -54,6 +54,7 @@ describe("create eservice", () => { .with(true, () => randomArrayItem([false, true, undefined])) .with(false, () => false) .exhaustive(); + const personalData = randomArrayItem([false, true]); const eservice = await catalogService.createEService( { @@ -65,6 +66,7 @@ describe("create eservice", () => { isSignalHubEnabled, isConsumerDelegable, isClientAccessDelegable, + personalData, }, getMockContext({ authData: getMockAuthData(mockEService.producerId) }) ); @@ -111,6 +113,7 @@ describe("create eservice", () => { isSignalHubEnabled, isConsumerDelegable, isClientAccessDelegable, + personalData, }; const expectedEserviceWithDescriptor: EService = { ...mockEService, @@ -119,6 +122,7 @@ describe("create eservice", () => { isSignalHubEnabled, isConsumerDelegable, isClientAccessDelegable, + personalData, descriptors: [ { ...mockDescriptor, From f146f833a0044a44094a64e35000ea6b1b603e35 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 11 Sep 2025 16:10:01 +0200 Subject: [PATCH 027/180] Update test --- .../catalog-process/test/integration/updateEservice.test.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/catalog-process/test/integration/updateEservice.test.ts b/packages/catalog-process/test/integration/updateEservice.test.ts index 13e4c9db6b..972c0b9537 100644 --- a/packages/catalog-process/test/integration/updateEservice.test.ts +++ b/packages/catalog-process/test/integration/updateEservice.test.ts @@ -61,6 +61,7 @@ describe("update eService", () => { .with(true, () => randomArrayItem([false, true, undefined])) .with(false, () => false) .exhaustive(); + const personalData = randomArrayItem([false, true]); const descriptor: Descriptor = { ...getMockDescriptor(), @@ -84,6 +85,7 @@ describe("update eService", () => { isSignalHubEnabled, isConsumerDelegable, isClientAccessDelegable, + personalData, }, getMockContext({ authData: getMockAuthData(mockEService.producerId) }) ); @@ -94,6 +96,7 @@ describe("update eService", () => { isSignalHubEnabled, isConsumerDelegable, isClientAccessDelegable, + personalData, }; const writtenEvent = await readLastEserviceEvent(mockEService.id); From 250a3fc6ae88842a0863566d0524113ab9890e22 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 11 Sep 2025 16:47:16 +0200 Subject: [PATCH 028/180] Update test --- .../integration/patchUpdateEservice.test.ts | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/packages/catalog-process/test/integration/patchUpdateEservice.test.ts b/packages/catalog-process/test/integration/patchUpdateEservice.test.ts index 27ab8a4f42..d39c195d2b 100644 --- a/packages/catalog-process/test/integration/patchUpdateEservice.test.ts +++ b/packages/catalog-process/test/integration/patchUpdateEservice.test.ts @@ -48,8 +48,11 @@ import { apiTechnologyToTechnology, } from "../../src/model/domain/apiConverter.js"; -describe("update eService", () => { - const mockEService = { ...getMockEService(), isSignalHubEnabled: false }; +describe("patch update eService", () => { + const mockEService: EService = { + ...getMockEService(), + isSignalHubEnabled: false, + }; const mockDocument = getMockDocument(); it.each([ @@ -96,6 +99,16 @@ describe("update eService", () => { isConsumerDelegable: true, isClientAccessDelegable: true, }, + { + name: "New name", + description: "New description", + technology: "SOAP", + mode: "DELIVER", + isSignalHubEnabled: true, + isConsumerDelegable: true, + isClientAccessDelegable: true, + personalData: true, + }, ] as catalogApi.PatchUpdateEServiceSeed[])( "should write on event-store and update only the fields set in the seed, and leave undefined fields unchanged (seed #%#)", async (seed) => { @@ -147,6 +160,7 @@ describe("update eService", () => { seed.isConsumerDelegable ?? eservice.isConsumerDelegable, isClientAccessDelegable: seed.isClientAccessDelegable ?? eservice.isClientAccessDelegable, + personalData: seed.personalData ?? eservice.personalData, descriptors: eservice.descriptors.map((d) => ({ ...d, interface: wasTechnologyUpdated ? undefined : d.interface, From 5bacb99698033779a991f9087155cf0afba20921 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Wed, 17 Sep 2025 10:45:53 +0200 Subject: [PATCH 029/180] Update outbound dependency --- .../agreement-outbound-writer/package.json | 2 +- packages/catalog-outbound-writer/package.json | 2 +- .../delegation-outbound-writer/package.json | 2 +- .../package.json | 2 +- packages/purpose-outbound-writer/package.json | 2 +- packages/tenant-outbound-writer/package.json | 2 +- pnpm-lock.yaml | 30 +++++++++---------- 7 files changed, 21 insertions(+), 21 deletions(-) diff --git a/packages/agreement-outbound-writer/package.json b/packages/agreement-outbound-writer/package.json index 9ef02aed2e..ad5d26942e 100644 --- a/packages/agreement-outbound-writer/package.json +++ b/packages/agreement-outbound-writer/package.json @@ -28,7 +28,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.4", + "@pagopa/interop-outbound-models": "1.6.6", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/packages/catalog-outbound-writer/package.json b/packages/catalog-outbound-writer/package.json index fd2761a54e..5e1b744b1c 100644 --- a/packages/catalog-outbound-writer/package.json +++ b/packages/catalog-outbound-writer/package.json @@ -28,7 +28,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.4", + "@pagopa/interop-outbound-models": "1.6.6", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/packages/delegation-outbound-writer/package.json b/packages/delegation-outbound-writer/package.json index 54bdd9ecd6..19d84c84b8 100644 --- a/packages/delegation-outbound-writer/package.json +++ b/packages/delegation-outbound-writer/package.json @@ -27,7 +27,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.4", + "@pagopa/interop-outbound-models": "1.6.6", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/packages/eservice-template-outbound-writer/package.json b/packages/eservice-template-outbound-writer/package.json index 04e36d9aea..0445198b0f 100644 --- a/packages/eservice-template-outbound-writer/package.json +++ b/packages/eservice-template-outbound-writer/package.json @@ -27,7 +27,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.4", + "@pagopa/interop-outbound-models": "1.6.6", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/packages/purpose-outbound-writer/package.json b/packages/purpose-outbound-writer/package.json index 58e5488ea3..17e9a4d6d1 100644 --- a/packages/purpose-outbound-writer/package.json +++ b/packages/purpose-outbound-writer/package.json @@ -28,7 +28,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.4", + "@pagopa/interop-outbound-models": "1.6.6", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/packages/tenant-outbound-writer/package.json b/packages/tenant-outbound-writer/package.json index e6be711883..2b9d649e28 100644 --- a/packages/tenant-outbound-writer/package.json +++ b/packages/tenant-outbound-writer/package.json @@ -28,7 +28,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.4", + "@pagopa/interop-outbound-models": "1.6.6", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cb38c06936..f066ea1b1e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -40,8 +40,8 @@ importers: packages/agreement-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.4 - version: 1.6.4 + specifier: 1.6.6 + version: 1.6.6 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -1306,8 +1306,8 @@ importers: packages/catalog-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.4 - version: 1.6.4 + specifier: 1.6.6 + version: 1.6.6 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -2344,8 +2344,8 @@ importers: packages/delegation-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.4 - version: 1.6.4 + specifier: 1.6.6 + version: 1.6.6 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -2969,8 +2969,8 @@ importers: packages/eservice-template-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.4 - version: 1.6.4 + specifier: 1.6.6 + version: 1.6.6 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -4979,8 +4979,8 @@ importers: packages/purpose-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.4 - version: 1.6.4 + specifier: 1.6.6 + version: 1.6.6 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -5791,8 +5791,8 @@ importers: packages/tenant-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.4 - version: 1.6.4 + specifier: 1.6.6 + version: 1.6.6 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -7596,8 +7596,8 @@ packages: '@pagopa/eslint-config@3.0.0': resolution: {integrity: sha512-eYIPdiuYRbRPR5k0OuteRNqYb0Z2nfJ/lZohejB7ylfBeSDWwkaV8Z19AXP4RymE6oEesyPDZ6i0yNaE9tQrHw==} - '@pagopa/interop-outbound-models@1.6.4': - resolution: {integrity: sha512-7FFsV2Eh6mtxjg+PczM3ShnTR99uAWtHwHmXizpNafrKsJP3MYSRMy39yKIk+U0Ashb+7rjn8P2LDFwanOr0JQ==} + '@pagopa/interop-outbound-models@1.6.6': + resolution: {integrity: sha512-TPoI/RPRl5wFH1ui6eK4KdAEC+gq4tN2svifSSBLQBdQB7FccxO1kYBs+0ytCRJp8u/T48EbsT+d9wyYvlwHfw==} '@protobuf-ts/plugin-framework@2.9.4': resolution: {integrity: sha512-9nuX1kjdMliv+Pes8dQCKyVhjKgNNfwxVHg+tx3fLXSfZZRcUHMc1PMwB9/vTvc6gBKt9QGz5ERqSqZc0++E9A==} @@ -14601,7 +14601,7 @@ snapshots: - tsutils - typescript - '@pagopa/interop-outbound-models@1.6.4': + '@pagopa/interop-outbound-models@1.6.6': dependencies: '@protobuf-ts/runtime': 2.9.4 ts-pattern: 5.2.0 From 320379133697cdd5d91830020fc5cbc04f23835f Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Wed, 17 Sep 2025 14:27:17 +0200 Subject: [PATCH 030/180] Renaming --- .../src/services/validators.ts | 4 +- .../commons-test/src/riskAnalysisTestUtils.ts | 73 ++++++++++--------- .../risk-analysis/riskAnalysisValidation.ts | 4 +- .../src/services/eserviceTemplateService.ts | 4 +- .../src/services/purposeService.ts | 4 +- .../src/services/validators.ts | 14 ++-- 6 files changed, 52 insertions(+), 51 deletions(-) diff --git a/packages/catalog-process/src/services/validators.ts b/packages/catalog-process/src/services/validators.ts index b21a0ce950..331cab32d0 100644 --- a/packages/catalog-process/src/services/validators.ts +++ b/packages/catalog-process/src/services/validators.ts @@ -203,13 +203,13 @@ export function assertHasNoDraftOrWaitingForApprovalDescriptor( export function validateRiskAnalysisSchemaOrThrow( riskAnalysisForm: catalogApi.EServiceRiskAnalysisSeed["riskAnalysisForm"], tenantKind: TenantKind, - dateForValidation: Date + dateForExpirationValidation: Date ): RiskAnalysisValidatedForm { const result = validateRiskAnalysis( riskAnalysisForm, true, tenantKind, - dateForValidation + dateForExpirationValidation ); if (result.type === "invalid") { throw riskAnalysisValidationFailed(result.issues); diff --git a/packages/commons-test/src/riskAnalysisTestUtils.ts b/packages/commons-test/src/riskAnalysisTestUtils.ts index f94f8c1633..c133617da5 100644 --- a/packages/commons-test/src/riskAnalysisTestUtils.ts +++ b/packages/commons-test/src/riskAnalysisTestUtils.ts @@ -67,7 +67,7 @@ export const validRiskAnalysis3_0_Pa: RiskAnalysisFormToValidate = { }, }; -export const validatedRiskAnalysis2_0_Pa: RiskAnalysisValidatedForm = { +export const validatedRiskAnalysis2_0_Pa_Expired: RiskAnalysisValidatedForm = { version: "2.0", singleAnswers: [ { key: "purpose", value: "INSTITUTIONAL" }, @@ -127,7 +127,7 @@ export const validatedRiskAnalysis3_0_Pa: RiskAnalysisValidatedForm = { ], }; -export const validRiskAnalysis1_0_Private: RiskAnalysisFormToValidate = { +export const expiredRiskAnalysis1_0_Private: RiskAnalysisFormToValidate = { version: "1.0", answers: { purpose: ["INSTITUTIONAL"], @@ -180,36 +180,37 @@ export const validRiskAnalysis2_0_Private: RiskAnalysisFormToValidate = { }, }; -export const validatedRiskAnalysis1_0_Private: RiskAnalysisValidatedForm = { - version: validRiskAnalysis1_0_Private.version, - singleAnswers: [ - { key: "purpose", value: "INSTITUTIONAL" }, - { key: "institutionalPurpose", value: "MyPurpose" }, - { key: "usesPersonalData", value: "YES" }, - { key: "otherPersonalDataTypes", value: "MyDataTypes" }, - { key: "legalObligationReference", value: "YES" }, - { key: "legalBasisPublicInterest", value: "RULE_OF_LAW" }, - { key: "ruleOfLawText", value: "TheLaw" }, - { key: "knowsDataQuantity", value: "NO" }, - { key: "dataDownload", value: "YES" }, - { key: "deliveryMethod", value: "CLEARTEXT" }, - { key: "policyProvided", value: "NO" }, - { key: "confirmPricipleIntegrityAndDiscretion", value: "true" }, - { key: "reasonPolicyNotProvided", value: "Test" }, - { key: "doneDpia", value: "NO" }, - { key: "dataRetentionPeriod", value: "10" }, - { key: "purposePursuit", value: "MERE_CORRECTNESS" }, - { - key: "checkedExistenceMereCorrectnessInteropCatalogue", - value: "true", - }, - { key: "declarationConfirmGDPR", value: "true" }, - ], - multiAnswers: [ - { key: "personalDataTypes", values: ["OTHER"] }, - { key: "legalBasis", values: ["LEGAL_OBLIGATION", "PUBLIC_INTEREST"] }, - ], -}; +export const validatedRiskAnalysis1_0_Private_Expired: RiskAnalysisValidatedForm = + { + version: expiredRiskAnalysis1_0_Private.version, + singleAnswers: [ + { key: "purpose", value: "INSTITUTIONAL" }, + { key: "institutionalPurpose", value: "MyPurpose" }, + { key: "usesPersonalData", value: "YES" }, + { key: "otherPersonalDataTypes", value: "MyDataTypes" }, + { key: "legalObligationReference", value: "YES" }, + { key: "legalBasisPublicInterest", value: "RULE_OF_LAW" }, + { key: "ruleOfLawText", value: "TheLaw" }, + { key: "knowsDataQuantity", value: "NO" }, + { key: "dataDownload", value: "YES" }, + { key: "deliveryMethod", value: "CLEARTEXT" }, + { key: "policyProvided", value: "NO" }, + { key: "confirmPricipleIntegrityAndDiscretion", value: "true" }, + { key: "reasonPolicyNotProvided", value: "Test" }, + { key: "doneDpia", value: "NO" }, + { key: "dataRetentionPeriod", value: "10" }, + { key: "purposePursuit", value: "MERE_CORRECTNESS" }, + { + key: "checkedExistenceMereCorrectnessInteropCatalogue", + value: "true", + }, + { key: "declarationConfirmGDPR", value: "true" }, + ], + multiAnswers: [ + { key: "personalDataTypes", values: ["OTHER"] }, + { key: "legalBasis", values: ["LEGAL_OBLIGATION", "PUBLIC_INTEREST"] }, + ], + }; export const validatedRiskAnalysis2_0_Private: RiskAnalysisValidatedForm = { version: validRiskAnalysis2_0_Private.version, @@ -284,13 +285,13 @@ export const getMockExpiredRiskAnalysis = ( match(producerTenantKind) .with(tenantKind.PA, () => riskAnalysisValidatedFormToNewRiskAnalysis( - validatedRiskAnalysis2_0_Pa, + validatedRiskAnalysis2_0_Pa_Expired, generateMock(z.string()) ) ) .with(tenantKind.PRIVATE, tenantKind.GSP, tenantKind.SCP, () => riskAnalysisValidatedFormToNewRiskAnalysis( - validatedRiskAnalysis1_0_Private, + validatedRiskAnalysis1_0_Private_Expired, generateMock(z.string()) ) ) @@ -316,12 +317,12 @@ export const getMockExpiredRiskAnalysisForm = ( match(producerTenantKind) .with(tenantKind.PA, () => riskAnalysisValidatedFormToNewRiskAnalysisForm( - validatedRiskAnalysis2_0_Pa + validatedRiskAnalysis2_0_Pa_Expired ) ) .with(tenantKind.PRIVATE, tenantKind.GSP, tenantKind.SCP, () => riskAnalysisValidatedFormToNewRiskAnalysisForm( - validatedRiskAnalysis1_0_Private + validatedRiskAnalysis1_0_Private_Expired ) ) .exhaustive(); diff --git a/packages/commons/src/risk-analysis/riskAnalysisValidation.ts b/packages/commons/src/risk-analysis/riskAnalysisValidation.ts index ced147567c..1e895292b2 100644 --- a/packages/commons/src/risk-analysis/riskAnalysisValidation.ts +++ b/packages/commons/src/risk-analysis/riskAnalysisValidation.ts @@ -31,7 +31,7 @@ export function validateRiskAnalysis( riskAnalysisForm: RiskAnalysisFormToValidate, schemaOnlyValidation: boolean, tenantKind: TenantKind, - dateForValidation: Date + dateForExpirationValidation: Date ): RiskAnalysisValidationResult { const formRulesForValidation = getFormRulesByVersion( tenantKind, @@ -46,7 +46,7 @@ export function validateRiskAnalysis( if ( formRulesForValidation.expiration && - formRulesForValidation.expiration < dateForValidation + formRulesForValidation.expiration < dateForExpirationValidation ) { return invalidResult([ expiredRulesVersionError(riskAnalysisForm.version, tenantKind), diff --git a/packages/eservice-template-process/src/services/eserviceTemplateService.ts b/packages/eservice-template-process/src/services/eserviceTemplateService.ts index 36e3c44cda..f7690b003c 100644 --- a/packages/eservice-template-process/src/services/eserviceTemplateService.ts +++ b/packages/eservice-template-process/src/services/eserviceTemplateService.ts @@ -243,13 +243,13 @@ const replaceEServiceTemplateVersion = ( export function validateRiskAnalysisSchemaOrThrow( riskAnalysisForm: eserviceTemplateApi.EServiceTemplateRiskAnalysisSeed["riskAnalysisForm"], tenantKind: TenantKind, - dateForValidation: Date + dateForExpirationValidation: Date ): RiskAnalysisValidatedForm { const result = validateRiskAnalysis( riskAnalysisForm, true, tenantKind, - dateForValidation + dateForExpirationValidation ); if (result.type === "invalid") { throw riskAnalysisValidationFailed(result.issues); diff --git a/packages/purpose-process/src/services/purposeService.ts b/packages/purpose-process/src/services/purposeService.ts index c8f0af9d3d..7471401a18 100644 --- a/packages/purpose-process/src/services/purposeService.ts +++ b/packages/purpose-process/src/services/purposeService.ts @@ -1003,7 +1003,7 @@ export function purposeServiceBuilder( riskAnalysisFormToRiskAnalysisFormToValidate(riskAnalysisForm), schemaOnlyValidation: false, tenantKind, - dateForValidation: new Date(), // beware: if the purpose version was waiting for approval, a new RA might have been published + dateForExpirationValidation: new Date(), // beware: if the purpose version was waiting for approval, a new RA might have been published }); } @@ -1340,7 +1340,7 @@ export function purposeServiceBuilder( ), schemaOnlyValidation: false, tenantKind: producerKind, - dateForValidation: createdAt, + dateForExpirationValidation: createdAt, }); const newVersion: PurposeVersion = { diff --git a/packages/purpose-process/src/services/validators.ts b/packages/purpose-process/src/services/validators.ts index 3c50a5aef0..5b1b03cf00 100644 --- a/packages/purpose-process/src/services/validators.ts +++ b/packages/purpose-process/src/services/validators.ts @@ -50,7 +50,7 @@ export const isRiskAnalysisFormValid = ( riskAnalysisForm: RiskAnalysisForm | undefined, schemaOnlyValidation: boolean, tenantKind: TenantKind, - dateForValidation: Date + dateForExpirationValidation: Date ): boolean => { if (riskAnalysisForm === undefined) { return false; @@ -60,7 +60,7 @@ export const isRiskAnalysisFormValid = ( riskAnalysisFormToRiskAnalysisFormToValidate(riskAnalysisForm), schemaOnlyValidation, tenantKind, - dateForValidation + dateForExpirationValidation ).type === "valid" ); } @@ -116,18 +116,18 @@ export function validateRiskAnalysisOrThrow({ riskAnalysisForm, schemaOnlyValidation, tenantKind, - dateForValidation, + dateForExpirationValidation, }: { riskAnalysisForm: purposeApi.RiskAnalysisFormSeed; schemaOnlyValidation: boolean; tenantKind: TenantKind; - dateForValidation: Date; + dateForExpirationValidation: Date; }): RiskAnalysisValidatedForm { const result = validateRiskAnalysis( riskAnalysisForm, schemaOnlyValidation, tenantKind, - dateForValidation + dateForExpirationValidation ); return match(result) .with({ type: "invalid" }, ({ issues }) => { @@ -141,7 +141,7 @@ export function validateAndTransformRiskAnalysis( riskAnalysisForm: purposeApi.RiskAnalysisFormSeed | undefined, schemaOnlyValidation: boolean, tenantKind: TenantKind, - dateForValidation: Date + dateForExpirationValidation: Date ): PurposeRiskAnalysisForm | undefined { if (!riskAnalysisForm) { return undefined; @@ -150,7 +150,7 @@ export function validateAndTransformRiskAnalysis( riskAnalysisForm, schemaOnlyValidation, tenantKind, - dateForValidation, + dateForExpirationValidation, }); return { From a1f9876d7bf6d17444f5b006cf6dd76998c2f057 Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Thu, 18 Sep 2025 08:55:49 +0200 Subject: [PATCH 031/180] Added EServicePersonalDataUpdatedAfterPublish events --- packages/catalog-process/src/model/domain/errors.ts | 2 +- packages/events-signer/src/handlers/handleCatalogMessageV2.ts | 3 ++- .../m2m-event-dispatcher/src/handlers/handleEServiceEvent.ts | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/catalog-process/src/model/domain/errors.ts b/packages/catalog-process/src/model/domain/errors.ts index af4268a297..2f5a193bbc 100644 --- a/packages/catalog-process/src/model/domain/errors.ts +++ b/packages/catalog-process/src/model/domain/errors.ts @@ -485,4 +485,4 @@ export function eservicePersonalDataCanOnlyBeSetOnce( code: "eservicePersonalDataCanOnlyBeSetOnce", title: "EService personalData can only be set once", }); -} \ No newline at end of file +} diff --git a/packages/events-signer/src/handlers/handleCatalogMessageV2.ts b/packages/events-signer/src/handlers/handleCatalogMessageV2.ts index 5183aa5cb9..7c068c5610 100644 --- a/packages/events-signer/src/handlers/handleCatalogMessageV2.ts +++ b/packages/events-signer/src/handlers/handleCatalogMessageV2.ts @@ -102,7 +102,8 @@ export const handleCatalogMessageV2 = async ( "EServiceDescriptorDocumentUpdatedByTemplateUpdate", "EServiceDescriptorDocumentDeletedByTemplateUpdate", "EServiceSignalHubEnabled", - "EServiceSignalHubDisabled" + "EServiceSignalHubDisabled", + "EServicePersonalDataUpdatedAfterPublish" ), }, (event) => { diff --git a/packages/m2m-event-dispatcher/src/handlers/handleEServiceEvent.ts b/packages/m2m-event-dispatcher/src/handlers/handleEServiceEvent.ts index 3263baf090..ba7f5f1cdd 100644 --- a/packages/m2m-event-dispatcher/src/handlers/handleEServiceEvent.ts +++ b/packages/m2m-event-dispatcher/src/handlers/handleEServiceEvent.ts @@ -54,7 +54,8 @@ export async function handleEServiceEvent( "EServiceDescriptorDocumentDeletedByTemplateUpdate", "EServiceDescriptorDocumentUpdatedByTemplateUpdate", "EServiceSignalHubEnabled", - "EServiceSignalHubDisabled" + "EServiceSignalHubDisabled", + "EServicePersonalDataUpdatedAfterPublish" ), }, () => Promise.resolve(void 0) From c8e76f402f987dafa2e0c18984cb49fcce4e11d0 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 18 Sep 2025 09:29:22 +0200 Subject: [PATCH 032/180] Fix import --- .../test/riskAnalysisValidation.integration.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/commons-test/test/riskAnalysisValidation.integration.test.ts b/packages/commons-test/test/riskAnalysisValidation.integration.test.ts index 20a32364e8..e5239f2dd4 100644 --- a/packages/commons-test/test/riskAnalysisValidation.integration.test.ts +++ b/packages/commons-test/test/riskAnalysisValidation.integration.test.ts @@ -14,8 +14,8 @@ import { } from "pagopa-interop-commons"; import { tenantKind } from "pagopa-interop-models"; import { + expiredRiskAnalysis1_0_Private, expiredRiskAnalysis2_0_Pa, - validRiskAnalysis1_0_Private, validRiskAnalysis2_0_Private, validRiskAnalysis3_0_Pa, validSchemaOnlyRiskAnalysis2_0_Private, @@ -191,7 +191,7 @@ describe("Risk Analysis Validation", () => { const expiredVersionForPrivate = "1.0"; const expiredRiskAnalysis2: RiskAnalysisFormToValidate = { - ...validRiskAnalysis1_0_Private, + ...expiredRiskAnalysis1_0_Private, version: expiredVersionForPrivate, }; From 8243f9e6467b1345ed8a3c8562acde22d8faadd6 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 18 Sep 2025 10:18:51 +0200 Subject: [PATCH 033/180] Set feature flag --- packages/catalog-process/.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/catalog-process/.env b/packages/catalog-process/.env index 3acb37a66e..3ceffdc48c 100644 --- a/packages/catalog-process/.env +++ b/packages/catalog-process/.env @@ -69,4 +69,4 @@ READMODEL_SQL_DB_SCHEMA_ESERVICE_TEMPLATE="readmodel_eservice_template" FEATURE_FLAG_AGREEMENT_APPROVAL_POLICY_UPDATE=true -FEATURE_FLAG_ESERVICE_PERSONAL_DATA=false +FEATURE_FLAG_ESERVICE_PERSONAL_DATA=true From 2dc02cb28e1037da8f646cf16bd92110c3cbfa37 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 18 Sep 2025 11:02:56 +0200 Subject: [PATCH 034/180] Add personalData in M2M gateway --- packages/api-clients/open-api/m2mGatewayApi.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/api-clients/open-api/m2mGatewayApi.yml b/packages/api-clients/open-api/m2mGatewayApi.yml index 9e2ec6149e..578e80c4d1 100644 --- a/packages/api-clients/open-api/m2mGatewayApi.yml +++ b/packages/api-clients/open-api/m2mGatewayApi.yml @@ -11608,6 +11608,8 @@ components: templateId: type: string format: uuid + personalData: + type: boolean required: - id - producerId @@ -11638,6 +11640,8 @@ components: type: boolean isClientAccessDelegable: type: boolean + personalData: + type: boolean EServiceDescriptor: type: object additionalProperties: false @@ -11962,6 +11966,8 @@ components: type: boolean isClientAccessDelegable: type: boolean + personalData: + type: boolean EServiceNameUpdateSeed: type: object additionalProperties: false From cf5434ff8dc85a2e48f2d2d20af864da929237d4 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 18 Sep 2025 11:15:52 +0200 Subject: [PATCH 035/180] Fix bff api --- packages/api-clients/open-api/bffApi.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/api-clients/open-api/bffApi.yml b/packages/api-clients/open-api/bffApi.yml index 266b578ea8..9fbc0cbbac 100644 --- a/packages/api-clients/open-api/bffApi.yml +++ b/packages/api-clients/open-api/bffApi.yml @@ -21613,6 +21613,8 @@ components: type: boolean isClientAccessDelegable: type: boolean + personalData: + type: boolean UpdateEServiceDescriptorQuotas: required: - voucherLifespan @@ -21968,6 +21970,8 @@ components: type: boolean isClientAccessDelegable: type: boolean + personalData: + type: boolean ProducerEServiceDetails: type: object additionalProperties: false @@ -22000,6 +22004,8 @@ components: type: boolean isClientAccessDelegable: type: boolean + personalData: + type: boolean EServiceMode: type: string description: Risk Analysis Mode @@ -22196,6 +22202,8 @@ components: type: boolean isClientAccessDelegable: type: boolean + personalData: + type: boolean ProducerDescriptorEServiceProducer: type: object additionalProperties: false From ada12454c5b2c331e971f27829dd92680bba6eff Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 18 Sep 2025 11:18:11 +0200 Subject: [PATCH 036/180] Use feature flag --- .../catalog-process/src/services/catalogService.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/catalog-process/src/services/catalogService.ts b/packages/catalog-process/src/services/catalogService.ts index 559b3bb6db..515081519b 100644 --- a/packages/catalog-process/src/services/catalogService.ts +++ b/packages/catalog-process/src/services/catalogService.ts @@ -3969,10 +3969,12 @@ async function updateDraftEService( ) .exhaustive(); - const updatedPersonalData = match(type) - .with("put", () => personalData) - .with("patch", () => personalData ?? eservice.data.personalData) - .exhaustive(); + const updatedPersonalData = config.featureFlagEservicePersonalData + ? match(type) + .with("put", () => personalData) + .with("patch", () => personalData ?? eservice.data.personalData) + .exhaustive() + : undefined; const updatedEService: EService = { ...eservice.data, From f29d39d998c1013613b232f301ac71569c7e94e5 Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Fri, 19 Sep 2025 12:03:06 +0200 Subject: [PATCH 037/180] Updated domains.eservice sql with personal_data --- docker/domains-analytics-db/domains-init.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/docker/domains-analytics-db/domains-init.sql b/docker/domains-analytics-db/domains-init.sql index a73464b8f7..86de271441 100644 --- a/docker/domains-analytics-db/domains-init.sql +++ b/docker/domains-analytics-db/domains-init.sql @@ -26,6 +26,7 @@ CREATE TABLE domains.eservice ( is_consumer_delegable BOOLEAN, is_client_access_delegable BOOLEAN, template_id VARCHAR(36), + personal_data BOOLEAN, deleted BOOLEAN, PRIMARY KEY (id) ); From 3ca7cadc782b5dae9b50df6e4a4d92cb5d05d728 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Fri, 19 Sep 2025 15:26:59 +0200 Subject: [PATCH 038/180] Fix aggregator --- packages/readmodel/src/catalog/aggregators.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/readmodel/src/catalog/aggregators.ts b/packages/readmodel/src/catalog/aggregators.ts index ed7bb2c75b..f8e11fccfa 100644 --- a/packages/readmodel/src/catalog/aggregators.ts +++ b/packages/readmodel/src/catalog/aggregators.ts @@ -284,7 +284,7 @@ export const aggregateEservice = ({ templateId: unsafeBrandId(eserviceSQL.templateId), } : {}), - ...(eserviceSQL.personalData + ...(eserviceSQL.personalData !== null ? { personalData: eserviceSQL.personalData, } From 5fea43cb12883409b29abcfd40aa33c789eb173f Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Fri, 19 Sep 2025 15:27:28 +0200 Subject: [PATCH 039/180] Add error --- packages/catalog-process/src/model/domain/errors.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/catalog-process/src/model/domain/errors.ts b/packages/catalog-process/src/model/domain/errors.ts index 2f5a193bbc..e25e2b886f 100644 --- a/packages/catalog-process/src/model/domain/errors.ts +++ b/packages/catalog-process/src/model/domain/errors.ts @@ -56,6 +56,7 @@ export const errorCodes = { checksumDuplicate: "0040", attributeDuplicatedInGroup: "0041", eservicePersonalDataCanOnlyBeSetOnce: "0042", + eservicePersonalDataMustBeSet: "0043", }; export type ErrorCodes = keyof typeof errorCodes; @@ -486,3 +487,14 @@ export function eservicePersonalDataCanOnlyBeSetOnce( title: "EService personalData can only be set once", }); } + +export function eservicePersonalDataMustBeSet( + eserviceId: EServiceId, + descriptorId: DescriptorId +): ApiError { + return new ApiError({ + detail: `Descriptor ${descriptorId} in eservice ${eserviceId} can't be published because personalData flag must be set for the eservice`, + code: "eservicePersonalDataMustBeSet", + title: "EService personalData must be set before publication", + }); +} From 17a10ac0367eb44a21125fa81f989cfc7a65634a Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Fri, 19 Sep 2025 15:28:03 +0200 Subject: [PATCH 040/180] Add check --- packages/catalog-process/src/services/catalogService.ts | 5 +++++ .../test/integration/publishDescriptor.test.ts | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/packages/catalog-process/src/services/catalogService.ts b/packages/catalog-process/src/services/catalogService.ts index 97d135b98d..8015536f1b 100644 --- a/packages/catalog-process/src/services/catalogService.ts +++ b/packages/catalog-process/src/services/catalogService.ts @@ -101,6 +101,7 @@ import { checksumDuplicate, attributeDuplicatedInGroup, eservicePersonalDataCanOnlyBeSetOnce, + eservicePersonalDataMustBeSet, } from "../model/domain/errors.js"; import { ApiGetEServicesFilters, Consumer } from "../model/domain/models.js"; import { @@ -1630,6 +1631,10 @@ export function catalogServiceBuilder( throw audienceCannotBeEmpty(descriptor.id); } + if (eservice.data.personalData === undefined) { + throw eservicePersonalDataMustBeSet(eserviceId, descriptorId); + } + if (producerDelegation) { const eserviceWithWaitingForApprovalDescriptor = replaceDescriptor( eservice.data, diff --git a/packages/catalog-process/test/integration/publishDescriptor.test.ts b/packages/catalog-process/test/integration/publishDescriptor.test.ts index 11f7669c76..722eeb86fb 100644 --- a/packages/catalog-process/test/integration/publishDescriptor.test.ts +++ b/packages/catalog-process/test/integration/publishDescriptor.test.ts @@ -72,6 +72,7 @@ describe("publish descriptor", () => { ...mockEService, mode: eserviceMode.deliver, descriptors: [descriptor], + personalData: false, }; await addOneEService(eservice); const publishDescriptorResponse = await catalogService.publishDescriptor( @@ -134,6 +135,7 @@ describe("publish descriptor", () => { mode: eserviceMode.receive, descriptors: [descriptor], riskAnalysis: [riskAnalysis], + personalData: false, }; await addOneTenant(producer); @@ -199,6 +201,7 @@ describe("publish descriptor", () => { mode: eserviceMode.receive, descriptors: [descriptor], riskAnalysis: [riskAnalysis], + personalData: false, }; const delegate = { @@ -268,6 +271,7 @@ describe("publish descriptor", () => { const eservice: EService = { ...mockEService, descriptors: [descriptor1, descriptor2], + personalData: false, }; await addOneEService(eservice); await catalogService.publishDescriptor( From 6277c4c8138438860f8417d56edab891d95102af Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Fri, 19 Sep 2025 15:26:59 +0200 Subject: [PATCH 041/180] Fix aggregator --- packages/readmodel/src/catalog/aggregators.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/readmodel/src/catalog/aggregators.ts b/packages/readmodel/src/catalog/aggregators.ts index ed7bb2c75b..f8e11fccfa 100644 --- a/packages/readmodel/src/catalog/aggregators.ts +++ b/packages/readmodel/src/catalog/aggregators.ts @@ -284,7 +284,7 @@ export const aggregateEservice = ({ templateId: unsafeBrandId(eserviceSQL.templateId), } : {}), - ...(eserviceSQL.personalData + ...(eserviceSQL.personalData !== null ? { personalData: eserviceSQL.personalData, } From d19c96c01e3512b85a18421f0f117c236c47ccaf Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Fri, 19 Sep 2025 15:30:28 +0200 Subject: [PATCH 042/180] Fix test --- .../catalog-process/test/integration/publishDescriptor.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/catalog-process/test/integration/publishDescriptor.test.ts b/packages/catalog-process/test/integration/publishDescriptor.test.ts index 722eeb86fb..1ac1af3735 100644 --- a/packages/catalog-process/test/integration/publishDescriptor.test.ts +++ b/packages/catalog-process/test/integration/publishDescriptor.test.ts @@ -333,6 +333,7 @@ describe("publish descriptor", () => { const eservice: EService = { ...mockEService, descriptors: [descriptor1, descriptor2], + personalData: false, }; await addOneEService(eservice); const tenant: Tenant = { From 12cc76d99931abadb688e26f0a06519275208eef Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Fri, 19 Sep 2025 15:34:47 +0200 Subject: [PATCH 043/180] Use feature flag during the check --- packages/catalog-process/src/services/catalogService.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/catalog-process/src/services/catalogService.ts b/packages/catalog-process/src/services/catalogService.ts index 8015536f1b..33ba0655cc 100644 --- a/packages/catalog-process/src/services/catalogService.ts +++ b/packages/catalog-process/src/services/catalogService.ts @@ -1631,7 +1631,10 @@ export function catalogServiceBuilder( throw audienceCannotBeEmpty(descriptor.id); } - if (eservice.data.personalData === undefined) { + if ( + config.featureFlagEservicePersonalData && + eservice.data.personalData === undefined + ) { throw eservicePersonalDataMustBeSet(eserviceId, descriptorId); } From 1eec6bf31d7fe7e5b86b7002ce7894d2f6062a00 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Fri, 19 Sep 2025 15:36:22 +0200 Subject: [PATCH 044/180] Add error in mapper --- packages/catalog-process/src/utilities/errorMappers.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/catalog-process/src/utilities/errorMappers.ts b/packages/catalog-process/src/utilities/errorMappers.ts index 00c473e869..c4872b13a5 100644 --- a/packages/catalog-process/src/utilities/errorMappers.ts +++ b/packages/catalog-process/src/utilities/errorMappers.ts @@ -297,6 +297,7 @@ export const publishDescriptorErrorMapper = ( "riskAnalysisNotValid", "notValidDescriptor", "audienceCannotBeEmpty", + "eservicePersonalDataMustBeSet", () => HTTP_STATUS_BAD_REQUEST ) .with("operationForbidden", () => HTTP_STATUS_FORBIDDEN) From 5c3e44e1ffc1d539a7f0be294a9ff897fcc26431 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Fri, 19 Sep 2025 15:37:10 +0200 Subject: [PATCH 045/180] Add error in api test --- packages/catalog-process/test/api/publishDescriptor.test.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/catalog-process/test/api/publishDescriptor.test.ts b/packages/catalog-process/test/api/publishDescriptor.test.ts index c129eb1cea..302a992815 100644 --- a/packages/catalog-process/test/api/publishDescriptor.test.ts +++ b/packages/catalog-process/test/api/publishDescriptor.test.ts @@ -23,6 +23,7 @@ import { eServiceDescriptorNotFound, eServiceDescriptorWithoutInterface, eServiceNotFound, + eservicePersonalDataMustBeSet, eServiceRiskAnalysisIsRequired, notValidDescriptorState, riskAnalysisNotValid, @@ -120,6 +121,10 @@ describe("API /eservices/{eServiceId}/descriptors/{descriptorId}/publish authori error: audienceCannotBeEmpty(descriptor.id), expectedStatus: 400, }, + { + error: eservicePersonalDataMustBeSet(mockEService.id, descriptor.id), + expectedStatus: 400, + }, ])( "Should return $expectedStatus for $error.code", async ({ error, expectedStatus }) => { From e27ba62f3df8e86c824db5170759e473ac897adc Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Fri, 19 Sep 2025 15:43:12 +0200 Subject: [PATCH 046/180] Add test --- .../integration/publishDescriptor.test.ts | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/packages/catalog-process/test/integration/publishDescriptor.test.ts b/packages/catalog-process/test/integration/publishDescriptor.test.ts index 1ac1af3735..8e9a9a3536 100644 --- a/packages/catalog-process/test/integration/publishDescriptor.test.ts +++ b/packages/catalog-process/test/integration/publishDescriptor.test.ts @@ -40,6 +40,7 @@ import { eServiceRiskAnalysisIsRequired, riskAnalysisNotValid, audienceCannotBeEmpty, + eservicePersonalDataMustBeSet, } from "../../src/model/domain/errors.js"; import { addOneEService, @@ -728,4 +729,30 @@ describe("publish descriptor", () => { ) ).rejects.toThrowError(audienceCannotBeEmpty(descriptor.id)); }); + + it("should throw eservicePersonalDataMustBeSet if the eservice has personalData undefined", async () => { + const descriptor: Descriptor = { + ...mockDescriptor, + state: descriptorState.draft, + interface: mockDocument, + }; + + const eservice: EService = { + ...mockEService, + descriptors: [descriptor], + personalData: undefined, + }; + + await addOneEService(eservice); + + expect( + catalogService.publishDescriptor( + eservice.id, + descriptor.id, + getMockContext({ authData: getMockAuthData(eservice.producerId) }) + ) + ).rejects.toThrowError( + eservicePersonalDataMustBeSet(eservice.id, descriptor.id) + ); + }); }); From f94f6f6e95c9172a652aa7b09ff938421dab0b59 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Fri, 19 Sep 2025 15:50:08 +0200 Subject: [PATCH 047/180] Fix outbound writer --- .../catalog-outbound-writer/src/converters/toOutboundEventV2.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/catalog-outbound-writer/src/converters/toOutboundEventV2.ts b/packages/catalog-outbound-writer/src/converters/toOutboundEventV2.ts index af0b1ec78f..d93b4df79f 100644 --- a/packages/catalog-outbound-writer/src/converters/toOutboundEventV2.ts +++ b/packages/catalog-outbound-writer/src/converters/toOutboundEventV2.ts @@ -97,6 +97,7 @@ export function toOutboundEventV2( { type: "EServiceNameUpdatedByTemplateUpdate" }, { type: "EServiceSignalHubEnabled" }, { type: "EServiceSignalHubDisabled" }, + { type: "EServicePersonalDataUpdatedAfterPublish" }, (msg) => ({ event_version: msg.event_version, type: msg.type, @@ -212,7 +213,6 @@ export function toOutboundEventV2( { type: "EServiceRiskAnalysisAdded" }, { type: "EServiceRiskAnalysisDeleted" }, { type: "EServiceRiskAnalysisUpdated" }, - { type: "EServicePersonalDataUpdatedAfterPublish" }, // TODO move to the first handler after outbound gets updated () => undefined ) .exhaustive(); From 8dc47d776908b987286960b332c23d0bb17d41eb Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Fri, 19 Sep 2025 16:39:36 +0200 Subject: [PATCH 048/180] Improve usage of feature flag --- .../src/services/catalogService.ts | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/catalog-process/src/services/catalogService.ts b/packages/catalog-process/src/services/catalogService.ts index 515081519b..d6c8a64f53 100644 --- a/packages/catalog-process/src/services/catalogService.ts +++ b/packages/catalog-process/src/services/catalogService.ts @@ -550,9 +550,9 @@ async function innerCreateEService( .with(true, () => seed.isClientAccessDelegable) .exhaustive(), templateId: template?.id, - personalData: config.featureFlagEservicePersonalData - ? seed.personalData - : undefined, + ...(config.featureFlagEservicePersonalData + ? { personalData: seed.personalData } + : {}), }; const eserviceCreationEvent = toCreateEventEServiceAdded( @@ -3969,12 +3969,10 @@ async function updateDraftEService( ) .exhaustive(); - const updatedPersonalData = config.featureFlagEservicePersonalData - ? match(type) - .with("put", () => personalData) - .with("patch", () => personalData ?? eservice.data.personalData) - .exhaustive() - : undefined; + const updatedPersonalData = match(type) + .with("put", () => personalData) + .with("patch", () => personalData ?? eservice.data.personalData) + .exhaustive(); const updatedEService: EService = { ...eservice.data, @@ -4005,7 +4003,9 @@ async function updateDraftEService( .with(false, () => false) .with(true, () => updatedIsClientAccessDelegable) .exhaustive(), - personalData: updatedPersonalData, + ...(config.featureFlagEservicePersonalData + ? { personalData: updatedPersonalData } + : {}), }; const event = await repository.createEvent( From 9b2c76bcd57d97c75dcef7dae4f29c24b1808ec3 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Fri, 19 Sep 2025 16:47:07 +0200 Subject: [PATCH 049/180] Add personalData in api spec --- packages/api-clients/open-api/bffApi.yml | 6 ++++++ packages/api-clients/open-api/eserviceTemplateApi.yml | 6 ++++++ packages/api-clients/open-api/m2mGatewayApi.yml | 2 ++ 3 files changed, 14 insertions(+) diff --git a/packages/api-clients/open-api/bffApi.yml b/packages/api-clients/open-api/bffApi.yml index deff818b0d..8a14a6a994 100644 --- a/packages/api-clients/open-api/bffApi.yml +++ b/packages/api-clients/open-api/bffApi.yml @@ -24637,6 +24637,8 @@ components: $ref: "#/components/schemas/EServiceMode" isSignalHubEnabled: type: boolean + personalData: + type: boolean draftVersion: $ref: "#/components/schemas/CompactEServiceTemplateVersion" EServiceTemplateVersionDetails: @@ -24757,6 +24759,8 @@ components: $ref: "#/components/schemas/EServiceMode" isSignalHubEnabled: type: boolean + personalData: + type: boolean EServiceTemplateSeed: type: object additionalProperties: false @@ -24787,6 +24791,8 @@ components: $ref: "#/components/schemas/VersionSeedForEServiceTemplateCreation" isSignalHubEnabled: type: boolean + personalData: + type: boolean InstanceEServiceSeed: type: object additionalProperties: false diff --git a/packages/api-clients/open-api/eserviceTemplateApi.yml b/packages/api-clients/open-api/eserviceTemplateApi.yml index b0974d2e1d..0f8d1906ae 100644 --- a/packages/api-clients/open-api/eserviceTemplateApi.yml +++ b/packages/api-clients/open-api/eserviceTemplateApi.yml @@ -1268,6 +1268,8 @@ components: $ref: "#/components/schemas/VersionSeedForEServiceTemplateCreation" isSignalHubEnabled: type: boolean + personalData: + type: boolean UpdateEServiceTemplateSeed: type: object additionalProperties: false @@ -1296,6 +1298,8 @@ components: $ref: "#/components/schemas/EServiceMode" isSignalHubEnabled: type: boolean + personalData: + type: boolean VersionSeedForEServiceTemplateCreation: required: - voucherLifespan @@ -1538,6 +1542,8 @@ components: $ref: "#/components/schemas/EServiceMode" isSignalHubEnabled: type: boolean + personalData: + type: boolean EServiceMode: type: string description: Risk Analysis Mode diff --git a/packages/api-clients/open-api/m2mGatewayApi.yml b/packages/api-clients/open-api/m2mGatewayApi.yml index 578e80c4d1..c98f711cd1 100644 --- a/packages/api-clients/open-api/m2mGatewayApi.yml +++ b/packages/api-clients/open-api/m2mGatewayApi.yml @@ -11861,6 +11861,8 @@ components: $ref: "#/components/schemas/EServiceMode" isSignalHubEnabled: type: boolean + personalData: + type: boolean required: - id - creatorId From 8ad9b87882aeeae3cfc1b2a6b19ea9c0fc2685f2 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Fri, 19 Sep 2025 16:47:31 +0200 Subject: [PATCH 050/180] Add feature flag --- packages/eservice-template-process/.env | 1 + packages/eservice-template-process/src/config/config.ts | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/eservice-template-process/.env b/packages/eservice-template-process/.env index 23fd120698..b6545aa10f 100644 --- a/packages/eservice-template-process/.env +++ b/packages/eservice-template-process/.env @@ -60,3 +60,4 @@ READMODEL_SQL_DB_SCHEMA_PURPOSE_TEMPLATE="readmodel_purpose_template" READMODEL_SQL_DB_SCHEMA_TENANT="readmodel_tenant" FEATURE_FLAG_SQL=true +FEATURE_FLAG_ESERVICE_PERSONAL_DATA=true diff --git a/packages/eservice-template-process/src/config/config.ts b/packages/eservice-template-process/src/config/config.ts index 5e12e5e3bb..5d29adc919 100644 --- a/packages/eservice-template-process/src/config/config.ts +++ b/packages/eservice-template-process/src/config/config.ts @@ -7,6 +7,7 @@ import { ApplicationAuditProducerConfig, FeatureFlagSQLConfig, ReadModelSQLDbConfig, + FeatureFlagEServicePersonalDataConfig, } from "pagopa-interop-commons"; import { z } from "zod"; @@ -31,7 +32,8 @@ const EServiceTemplateProcessConfig = CommonHTTPServiceConfig.and( ) .and(ApplicationAuditProducerConfig) .and(FeatureFlagSQLConfig) - .and(ReadModelSQLDbConfig.optional()); + .and(ReadModelSQLDbConfig.optional()) + .and(FeatureFlagEServicePersonalDataConfig); export type EServiceTemplateProcessConfig = z.infer< typeof EServiceTemplateProcessConfig From 04473d3a993d6f34fdd271f308f5c024c5a7983a Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Fri, 19 Sep 2025 16:47:48 +0200 Subject: [PATCH 051/180] Add personalData --- docker/domains-analytics-db/domains-init.sql | 3 ++- docker/readmodel-db/eservice-template.sql | 1 + .../src/services/eserviceTemplateService.ts | 6 ++++++ .../proto/v2/eservice-template/eservice-template.proto | 1 + packages/models/src/eservice-template/eserviceTemplate.ts | 1 + 5 files changed, 11 insertions(+), 1 deletion(-) diff --git a/docker/domains-analytics-db/domains-init.sql b/docker/domains-analytics-db/domains-init.sql index 86de271441..c16f1a4a3c 100644 --- a/docker/domains-analytics-db/domains-init.sql +++ b/docker/domains-analytics-db/domains-init.sql @@ -516,6 +516,7 @@ CREATE TABLE IF NOT EXISTS domains.eservice_template ( created_at TIMESTAMP WITH TIME ZONE NOT NULL, mode VARCHAR(2048) NOT NULL, is_signal_hub_enabled BOOLEAN, + personal_data BOOLEAN, deleted BOOLEAN, PRIMARY KEY (id) ); @@ -604,4 +605,4 @@ CREATE TABLE IF NOT EXISTS domains.eservice_template_risk_analysis_answer ( value VARCHAR(65535) NOT NULL, deleted BOOLEAN, PRIMARY KEY (id) -); \ No newline at end of file +); diff --git a/docker/readmodel-db/eservice-template.sql b/docker/readmodel-db/eservice-template.sql index 1b71676e99..e831de0f6b 100644 --- a/docker/readmodel-db/eservice-template.sql +++ b/docker/readmodel-db/eservice-template.sql @@ -11,6 +11,7 @@ CREATE TABLE IF NOT EXISTS readmodel_eservice_template.eservice_template ( created_at TIMESTAMP WITH TIME ZONE NOT NULL, mode VARCHAR NOT NULL, is_signal_hub_enabled BOOLEAN, + personal_data BOOLEAN, PRIMARY KEY (id), CONSTRAINT eservice_template_id_metadata_version_unique UNIQUE (id, metadata_version) ); diff --git a/packages/eservice-template-process/src/services/eserviceTemplateService.ts b/packages/eservice-template-process/src/services/eserviceTemplateService.ts index f7690b003c..2c62f6102c 100644 --- a/packages/eservice-template-process/src/services/eserviceTemplateService.ts +++ b/packages/eservice-template-process/src/services/eserviceTemplateService.ts @@ -1222,6 +1222,9 @@ export function eserviceTemplateServiceBuilder( createdAt: creationDate, riskAnalysis: [], isSignalHubEnabled: seed.isSignalHubEnabled, + ...(config.featureFlagEservicePersonalData + ? { personalData: seed.personalData } + : {}), }; const eserviceTemplateCreationEvent = toCreateEventEServiceTemplateAdded( @@ -1303,6 +1306,9 @@ export function eserviceTemplateServiceBuilder( })) : eserviceTemplate.data.versions, isSignalHubEnabled: eserviceTemplateSeed.isSignalHubEnabled, + ...(config.featureFlagEservicePersonalData + ? { personalData: eserviceTemplateSeed.personalData } + : {}), }; const event = toCreateEventEServiceTemplateDraftUpdated( diff --git a/packages/models/proto/v2/eservice-template/eservice-template.proto b/packages/models/proto/v2/eservice-template/eservice-template.proto index f4b2bd38e8..127cee21b1 100644 --- a/packages/models/proto/v2/eservice-template/eservice-template.proto +++ b/packages/models/proto/v2/eservice-template/eservice-template.proto @@ -50,4 +50,5 @@ message EServiceTemplateV2 { repeated EServiceTemplateRiskAnalysisV2 riskAnalysis = 9; eservice.v2.EServiceModeV2 mode = 10; optional bool isSignalHubEnabled = 11; + optional bool personalData = 12; } diff --git a/packages/models/src/eservice-template/eserviceTemplate.ts b/packages/models/src/eservice-template/eserviceTemplate.ts index 7bf1f650e4..b08239ed97 100644 --- a/packages/models/src/eservice-template/eserviceTemplate.ts +++ b/packages/models/src/eservice-template/eserviceTemplate.ts @@ -70,6 +70,7 @@ export const EServiceTemplate = z.object({ technology: Technology, riskAnalysis: z.array(EServiceTemplateRiskAnalysis), mode: EServiceMode, + personalData: z.boolean().optional(), // Default values to be set in all e-service instances created from this template, unless the user provides a custom value isSignalHubEnabled: z.boolean().optional(), From cdf959816409840fc56c0ef14ee35f4a4a1af76c Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Fri, 19 Sep 2025 17:25:56 +0200 Subject: [PATCH 052/180] Update db model --- packages/readmodel-models/src/drizzle/schema.ts | 1 + packages/readmodel/src/eservice-template/aggregators.ts | 5 +++++ packages/readmodel/src/eservice-template/splitters.ts | 1 + 3 files changed, 7 insertions(+) diff --git a/packages/readmodel-models/src/drizzle/schema.ts b/packages/readmodel-models/src/drizzle/schema.ts index 777b92d8eb..4f939dd41e 100644 --- a/packages/readmodel-models/src/drizzle/schema.ts +++ b/packages/readmodel-models/src/drizzle/schema.ts @@ -75,6 +75,7 @@ export const eserviceTemplateInReadmodelEserviceTemplate = }).notNull(), mode: varchar().notNull(), isSignalHubEnabled: boolean("is_signal_hub_enabled"), + personalData: boolean("personal_data"), }, (table) => [ unique("eservice_template_id_metadata_version_unique").on( diff --git a/packages/readmodel/src/eservice-template/aggregators.ts b/packages/readmodel/src/eservice-template/aggregators.ts index c9b4433966..b350518cc0 100644 --- a/packages/readmodel/src/eservice-template/aggregators.ts +++ b/packages/readmodel/src/eservice-template/aggregators.ts @@ -188,6 +188,11 @@ export const aggregateEServiceTemplate = ({ ...(eserviceTemplateSQL.isSignalHubEnabled !== null ? { isSignalHubEnabled: eserviceTemplateSQL.isSignalHubEnabled } : {}), + ...(eserviceTemplateSQL.personalData !== null + ? { + personalData: eserviceTemplateSQL.personalData, + } + : {}), }; return { data: eserviceTemplate, diff --git a/packages/readmodel/src/eservice-template/splitters.ts b/packages/readmodel/src/eservice-template/splitters.ts index 2bb2f63426..eae7fa083d 100644 --- a/packages/readmodel/src/eservice-template/splitters.ts +++ b/packages/readmodel/src/eservice-template/splitters.ts @@ -325,4 +325,5 @@ const eserviceTemplateToEServiceTemplateSQL = ( technology: eserviceTemplate.technology, mode: eserviceTemplate.mode, isSignalHubEnabled: eserviceTemplate.isSignalHubEnabled ?? null, + personalData: eserviceTemplate.personalData ?? null, }); From a6d892dd424ff8b91b29cd9cce965d71b64fd348 Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Mon, 22 Sep 2025 09:01:16 +0200 Subject: [PATCH 053/180] test(bff): add PUT /eservices/:eserviceId and POST /eservices router api tests --- .../test/api/catalogRouter/createEService.test.ts | 1 + .../test/api/catalogRouter/updateEServiceById.test.ts | 6 ++++++ packages/backend-for-frontend/test/mockUtils.ts | 1 + 3 files changed, 8 insertions(+) diff --git a/packages/backend-for-frontend/test/api/catalogRouter/createEService.test.ts b/packages/backend-for-frontend/test/api/catalogRouter/createEService.test.ts index 17c4ad52ea..a68aa0cd10 100644 --- a/packages/backend-for-frontend/test/api/catalogRouter/createEService.test.ts +++ b/packages/backend-for-frontend/test/api/catalogRouter/createEService.test.ts @@ -55,6 +55,7 @@ describe("API POST /eservices", () => { { body: { ...mockEServiceSeed, isSignalHubEnabled: "invalid" } }, { body: { ...mockEServiceSeed, mode: "invalid" } }, { body: { ...mockEServiceSeed, technology: "invalid" } }, + { body: { ...mockEServiceSeed, personalData: "invalid" } }, ])( "Should return 400 if passed an invalid parameter: %s", async ({ body }) => { diff --git a/packages/backend-for-frontend/test/api/catalogRouter/updateEServiceById.test.ts b/packages/backend-for-frontend/test/api/catalogRouter/updateEServiceById.test.ts index d3ad97bf8f..104b9e9c0a 100644 --- a/packages/backend-for-frontend/test/api/catalogRouter/updateEServiceById.test.ts +++ b/packages/backend-for-frontend/test/api/catalogRouter/updateEServiceById.test.ts @@ -81,6 +81,12 @@ describe("API PUT /eservices/:eServiceId", () => { isClientAccessDelegable: "invalid", }, }, + { + body: { + ...mockUpdateEServiceSeed, + personalData: "invalid", + }, + }, ])( "Should return 400 if passed an invalid parameter", async ({ eServiceId, body }) => { diff --git a/packages/backend-for-frontend/test/mockUtils.ts b/packages/backend-for-frontend/test/mockUtils.ts index 64c73a9d67..a2bf60725c 100644 --- a/packages/backend-for-frontend/test/mockUtils.ts +++ b/packages/backend-for-frontend/test/mockUtils.ts @@ -368,6 +368,7 @@ export const getMockBffApiEServiceSeed = (): bffApi.EServiceSeed => ({ isSignalHubEnabled: generateMock(z.boolean().optional()), isClientAccessDelegable: generateMock(z.boolean().optional()), isConsumerDelegable: generateMock(z.boolean().optional()), + personalData: generateMock(z.boolean().optional()), }); export const getMockBffApiRejectDelegatedEServiceDescriptorSeed = From 5b9c39a0fe691fc76bd02a6706bff8d186769f09 Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Mon, 22 Sep 2025 09:01:47 +0200 Subject: [PATCH 054/180] test(m2m-gateway): add PATCH /eservices/:eserviceId and POST /eservices router api tests --- .../test/api/eservices/createEservice.test.ts | 1 + .../test/api/eservices/updateDraftEService.test.ts | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/packages/m2m-gateway/test/api/eservices/createEservice.test.ts b/packages/m2m-gateway/test/api/eservices/createEservice.test.ts index f8fde00bb2..5c37130db9 100644 --- a/packages/m2m-gateway/test/api/eservices/createEservice.test.ts +++ b/packages/m2m-gateway/test/api/eservices/createEservice.test.ts @@ -124,6 +124,7 @@ describe("POST /eservices router test", () => { // We currently do not support multiple audiences for consistency with front-end }, }, + { ...mockEserviceSeed, personalData: "invalidValue" }, ])( "Should return 400 if passed an invalid Eservice seed (seed #%#)", async (body) => { diff --git a/packages/m2m-gateway/test/api/eservices/updateDraftEService.test.ts b/packages/m2m-gateway/test/api/eservices/updateDraftEService.test.ts index 5d805a948d..50302f3d6b 100644 --- a/packages/m2m-gateway/test/api/eservices/updateDraftEService.test.ts +++ b/packages/m2m-gateway/test/api/eservices/updateDraftEService.test.ts @@ -99,6 +99,16 @@ describe("PATCH /eservices/:eserviceId router test", () => { isClientAccessDelegable: true, mode: "RECEIVE", }, + { + name: "updated name", + description: "updated description", + technology: "REST", + isSignalHubEnabled: true, + isConsumerDelegable: false, + isClientAccessDelegable: true, + mode: "RECEIVE", + personalData: true, + }, ] satisfies m2mGatewayApi.EServiceDraftUpdateSeed[])( "Should return 200 with partial seed and nullable fields (seed #%#)", async (seed) => { From 4ca86dade03c7121536de14e7f84f7fdb7f3350d Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Mon, 22 Sep 2025 09:05:51 +0200 Subject: [PATCH 055/180] test(catalog-readmodel-writer-sql): updated test with personalData --- .../catalog-readmodel-writer-sql/test/eserviceQueries.test.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/catalog-readmodel-writer-sql/test/eserviceQueries.test.ts b/packages/catalog-readmodel-writer-sql/test/eserviceQueries.test.ts index 4f1de50b1e..cc300393fc 100644 --- a/packages/catalog-readmodel-writer-sql/test/eserviceQueries.test.ts +++ b/packages/catalog-readmodel-writer-sql/test/eserviceQueries.test.ts @@ -76,6 +76,7 @@ describe("E-service queries", () => { isConsumerDelegable: true, isClientAccessDelegable: true, templateId: generateId(), + personalData: true, }; await catalogWriterService.upsertEService(eservice, 1); @@ -227,6 +228,7 @@ describe("E-service queries", () => { isConsumerDelegable: true, isClientAccessDelegable: true, templateId: generateId(), + personalData: true, }; await catalogWriterService.upsertEService(eservice, 1); From 3e44c8a10dd8a2ccaa0b195e6819088ee0b3929a Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Mon, 22 Sep 2025 09:11:58 +0200 Subject: [PATCH 056/180] test(bff): add POST /eservices/:eserviceId/personalData api test --- .../updateEServicePersonalData.test.ts | 70 +++++++++++++++++++ .../backend-for-frontend/test/mockUtils.ts | 5 ++ 2 files changed, 75 insertions(+) create mode 100644 packages/backend-for-frontend/test/api/catalogRouter/updateEServicePersonalData.test.ts diff --git a/packages/backend-for-frontend/test/api/catalogRouter/updateEServicePersonalData.test.ts b/packages/backend-for-frontend/test/api/catalogRouter/updateEServicePersonalData.test.ts new file mode 100644 index 0000000000..36d8581f1c --- /dev/null +++ b/packages/backend-for-frontend/test/api/catalogRouter/updateEServicePersonalData.test.ts @@ -0,0 +1,70 @@ +/* eslint-disable @typescript-eslint/explicit-function-return-type */ +import { beforeEach, describe, expect, it, vi } from "vitest"; +import { EServiceId, generateId } from "pagopa-interop-models"; +import request from "supertest"; +import { generateToken } from "pagopa-interop-commons-test/index.js"; +import { authRole } from "pagopa-interop-commons"; +import { bffApi } from "pagopa-interop-api-clients"; +import { api, clients } from "../../vitest.api.setup.js"; +import { + getMockBffApiEServicePersonalDataUpdateSeed, + getMockCatalogApiEService, +} from "../../mockUtils.js"; +import { appBasePath } from "../../../src/config/appBasePath.js"; + +describe("API POST /eservices/:eServiceId/personalData", () => { + const mockEServicePersonalDataUpdateSeed = + getMockBffApiEServicePersonalDataUpdateSeed(); + const mockEService = getMockCatalogApiEService(); + + const makeRequest = async ( + token: string, + eServiceId: EServiceId = mockEService.id, + body: bffApi.EServicePersonalDataUpdateSeed = mockEServicePersonalDataUpdateSeed + ) => + request(api) + .post(`${appBasePath}/eservices/${eServiceId}/personalData`) + .set("Authorization", `Bearer ${token}`) + .set("X-Correlation-Id", generateId()) + .send(body); + + beforeEach(() => { + clients.catalogProcessClient.updateEServicePersonalDataAfterPublish = vi + .fn() + .mockResolvedValue(mockEService); + }); + + it("Should return 204 if no error is thrown", async () => { + const token = generateToken(authRole.ADMIN_ROLE); + const res = await makeRequest(token); + expect(res.status).toBe(204); + }); + + it.each([ + { eServiceId: "invalid" as EServiceId }, + { body: {} }, + { + body: { + ...mockEServicePersonalDataUpdateSeed, + extraField: 1, + }, + }, + { + body: { + ...mockEServicePersonalDataUpdateSeed, + personalData: "invalid", + }, + }, + ])( + "Should return 400 if passed an invalid parameter", + async ({ eServiceId, body }) => { + const token = generateToken(authRole.ADMIN_ROLE); + const res = await makeRequest( + token, + eServiceId, + body as bffApi.EServicePersonalDataUpdateSeed + ); + expect(res.status).toBe(400); + } + ); +}); diff --git a/packages/backend-for-frontend/test/mockUtils.ts b/packages/backend-for-frontend/test/mockUtils.ts index a2bf60725c..f95c38f4c3 100644 --- a/packages/backend-for-frontend/test/mockUtils.ts +++ b/packages/backend-for-frontend/test/mockUtils.ts @@ -360,6 +360,11 @@ export const getMockBffApiInstanceEServiceSeed = isConsumerDelegable: generateMock(z.boolean().optional()), }); +export const getMockBffApiEServicePersonalDataUpdateSeed = + (): bffApi.EServicePersonalDataUpdateSeed => ({ + personalData: generateMock(z.boolean()), + }); + export const getMockBffApiEServiceSeed = (): bffApi.EServiceSeed => ({ name: generateMock(z.string()), description: generateMock(z.string()), From 9ba02a749288a4280578e9d011b636d3bff85148 Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Mon, 22 Sep 2025 09:13:56 +0200 Subject: [PATCH 057/180] test(catalog-process): add POST /eservices/:eserviceId/personalData api test --- .../api/updateEServicePersonalData.test.ts | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 packages/catalog-process/test/api/updateEServicePersonalData.test.ts diff --git a/packages/catalog-process/test/api/updateEServicePersonalData.test.ts b/packages/catalog-process/test/api/updateEServicePersonalData.test.ts new file mode 100644 index 0000000000..42ae77b2d4 --- /dev/null +++ b/packages/catalog-process/test/api/updateEServicePersonalData.test.ts @@ -0,0 +1,129 @@ +/* eslint-disable @typescript-eslint/explicit-function-return-type */ +import { describe, it, expect, vi } from "vitest"; +import request from "supertest"; +import { + Descriptor, + descriptorState, + EService, + EServiceId, + generateId, + operationForbidden, +} from "pagopa-interop-models"; +import { + generateToken, + randomArrayItem, + getMockDescriptor, + getMockEService, +} from "pagopa-interop-commons-test"; +import { AuthRole, authRole } from "pagopa-interop-commons"; +import { catalogApi } from "pagopa-interop-api-clients"; +import { api, catalogService } from "../vitest.api.setup.js"; +import { eServiceToApiEService } from "../../src/model/domain/apiConverter.js"; +import { + eServiceNotFound, + eserviceWithoutValidDescriptors, +} from "../../src/model/domain/errors.js"; + +describe("API /eservices/{eServiceId}/personalData authorization test", () => { + const descriptor: Descriptor = { + ...getMockDescriptor(), + state: descriptorState.published, + }; + + const mockEService: EService = { + ...getMockEService(), + descriptors: [descriptor], + }; + + const serviceResponse = mockEService; + const apiEservice = catalogApi.EService.parse( + eServiceToApiEService(mockEService) + ); + + const personalData = randomArrayItem([false, true]); + + const eserviceSeed: catalogApi.EServicePersonalDataUpdateSeed = { + personalData, + }; + + catalogService.updateEServicePersonalDataAfterPublish = vi + .fn() + .mockResolvedValue(serviceResponse); + + const makeRequest = async ( + token: string, + eServiceId: EServiceId, + body: catalogApi.EServicePersonalDataUpdateSeed = eserviceSeed + ) => + request(api) + .post(`/eservices/${eServiceId}/personalData`) + .set("Authorization", `Bearer ${token}`) + .set("X-Correlation-Id", generateId()) + .send(body); + + const authorizedRoles: AuthRole[] = [authRole.ADMIN_ROLE, authRole.API_ROLE]; + + it.each(authorizedRoles)( + "Should return 200 for user with role %s", + async (role) => { + const token = generateToken(role); + const res = await makeRequest(token, mockEService.id); + expect(res.status).toBe(200); + expect(res.body).toEqual(apiEservice); + } + ); + + it.each( + Object.values(authRole).filter((role) => !authorizedRoles.includes(role)) + )("Should return 403 for user with role %s", async (role) => { + const token = generateToken(role); + const res = await makeRequest(token, mockEService.id); + + expect(res.status).toBe(403); + }); + + it.each([ + { + error: eserviceWithoutValidDescriptors(mockEService.id), + expectedStatus: 409, + }, + { + error: eServiceNotFound(mockEService.id), + expectedStatus: 404, + }, + { + error: operationForbidden, + expectedStatus: 403, + }, + ])( + "Should return $expectedStatus for $error.code", + async ({ error, expectedStatus }) => { + catalogService.updateEServicePersonalDataAfterPublish = vi + .fn() + .mockRejectedValue(error); + + const token = generateToken(authRole.ADMIN_ROLE); + const res = await makeRequest(token, mockEService.id); + + expect(res.status).toBe(expectedStatus); + } + ); + + it.each([ + [{}, mockEService.id], + [{ personalData: "notABool" }, mockEService.id], + [{ ...eserviceSeed }, "invalidId"], + ])( + "Should return 400 if passed invalid personalData update params: %s (eServiceId: %s)", + async (body, eServiceId) => { + const token = generateToken(authRole.ADMIN_ROLE); + const res = await makeRequest( + token, + eServiceId as EServiceId, + body as catalogApi.EServicePersonalDataUpdateSeed + ); + + expect(res.status).toBe(400); + } + ); +}); From 01ab27a46d427a8bcbcd61a549d79e6d07858d5d Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Mon, 22 Sep 2025 09:15:24 +0200 Subject: [PATCH 058/180] test(catalog-process): add integration test EServicePersonalDataUpdatedAfterPublishV2 --- ...icePersonalDataUpdatedAfterPublish.test.ts | 150 ++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 packages/catalog-process/test/integration/updateEServicePersonalDataUpdatedAfterPublish.test.ts diff --git a/packages/catalog-process/test/integration/updateEServicePersonalDataUpdatedAfterPublish.test.ts b/packages/catalog-process/test/integration/updateEServicePersonalDataUpdatedAfterPublish.test.ts new file mode 100644 index 0000000000..edc0e28a97 --- /dev/null +++ b/packages/catalog-process/test/integration/updateEServicePersonalDataUpdatedAfterPublish.test.ts @@ -0,0 +1,150 @@ +/* eslint-disable @typescript-eslint/no-floating-promises */ +import { + decodeProtobufPayload, + getMockContext, + getMockAuthData, + getMockDocument, + getMockDescriptor, + getMockEService, +} from "pagopa-interop-commons-test"; +import { + Descriptor, + descriptorState, + EService, + toEServiceV2, + EServicePersonalDataUpdatedAfterPublishV2, + operationForbidden, +} from "pagopa-interop-models"; +import { expect, describe, it } from "vitest"; +import { + addOneEService, + catalogService, + readLastEserviceEvent, +} from "../integrationUtils.js"; +import { + eServiceNotFound, + eservicePersonalDataCanOnlyBeSetOnce, + eserviceWithoutValidDescriptors, +} from "../../src/model/domain/errors.js"; + +describe("update E-service personalData flag for an already created E-service", async () => { + it("should write on event-store for the update of the E-service personalData flag (undefined -> true)", async () => { + const descriptor: Descriptor = { + ...getMockDescriptor(descriptorState.published), + interface: getMockDocument(), + }; + + const eservice: EService = { + ...getMockEService(), + descriptors: [descriptor], + }; + + await addOneEService(eservice); + const newPersonalDataValue = true; + + const returnedEService = + await catalogService.updateEServicePersonalDataAfterPublish( + eservice.id, + newPersonalDataValue, + getMockContext({ authData: getMockAuthData(eservice.producerId) }) + ); + + const updatedEService: EService = { + ...eservice, + personalData: newPersonalDataValue, + }; + + const writtenEvent = await readLastEserviceEvent(eservice.id); + expect(writtenEvent).toMatchObject({ + stream_id: eservice.id, + version: "1", + type: "EServicePersonalDataUpdatedAfterPublish", + event_version: 2, + }); + + const writtenPayload = decodeProtobufPayload({ + messageType: EServicePersonalDataUpdatedAfterPublishV2, + payload: writtenEvent.data, + }); + + expect(writtenPayload.eservice).toEqual(toEServiceV2(updatedEService)); + expect(writtenPayload.eservice).toEqual(toEServiceV2(returnedEService)); + }); + + it.each([ + [true, true], + [false, false], + ])( + "should NOT write on event-store for the update of the E-service personalData flag if it was already set (%s -> %s)", + async (oldPersonalDataValue, newPersonalDataValue) => { + const descriptor: Descriptor = { + ...getMockDescriptor(descriptorState.published), + interface: getMockDocument(), + }; + + const eservice: EService = { + ...getMockEService(), + descriptors: [descriptor], + personalData: oldPersonalDataValue, + }; + + await addOneEService(eservice); + + await expect( + catalogService.updateEServicePersonalDataAfterPublish( + eservice.id, + newPersonalDataValue, + getMockContext({ authData: getMockAuthData(eservice.producerId) }) + ) + ).rejects.toThrowError(eservicePersonalDataCanOnlyBeSetOnce(eservice.id)); + } + ); + + it.each([true, false])( + "should throw eServiceNotFound if the eservice doesn't exist (with personalData flag set to %s)", + async (personalDataFlag) => { + const eservice = getMockEService(); + expect( + catalogService.updateEServicePersonalDataAfterPublish( + eservice.id, + personalDataFlag, + getMockContext({ authData: getMockAuthData(eservice.producerId) }) + ) + ).rejects.toThrowError(eServiceNotFound(eservice.id)); + } + ); + + it.each([true, false])( + "should throw operationForbidden if the requester is not the producer (with personalData flag set to %s)", + async (personalDataFlag) => { + const eservice = getMockEService(); + await addOneEService(eservice); + expect( + catalogService.updateEServicePersonalDataAfterPublish( + eservice.id, + personalDataFlag, + getMockContext({}) + ) + ).rejects.toThrowError(operationForbidden); + } + ); + + it.each([true, false])( + "should throw eserviceWithoutValidDescriptors if the eservice doesn't have any descriptors (with personalData flag set to %s)", + async (personalDataFlag) => { + const eservice: EService = { + ...getMockEService(), + personalData: personalDataFlag, + }; + + await addOneEService(eservice); + expect( + catalogService.updateEServicePersonalDataAfterPublish( + eservice.id, + personalDataFlag, + getMockContext({ authData: getMockAuthData(eservice.producerId) }) + ) + ).rejects.toThrowError(eserviceWithoutValidDescriptors(eservice.id)); + } + ); +}); From e6ba107067993ee178924d22aec95a0abb410b61 Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Mon, 22 Sep 2025 09:16:11 +0200 Subject: [PATCH 059/180] test(catalog-readmodel-writer-sql): add test EServicePersonalDataUpdatedAfterPublishV2 --- ...catalogReadmodelWriter.integration.test.ts | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/packages/catalog-readmodel-writer-sql/test/catalogReadmodelWriter.integration.test.ts b/packages/catalog-readmodel-writer-sql/test/catalogReadmodelWriter.integration.test.ts index d9d8b8f569..d0bec28ed9 100644 --- a/packages/catalog-readmodel-writer-sql/test/catalogReadmodelWriter.integration.test.ts +++ b/packages/catalog-readmodel-writer-sql/test/catalogReadmodelWriter.integration.test.ts @@ -39,6 +39,7 @@ import { EServiceDraftDescriptorUpdatedV2, EServiceEventEnvelope, EServiceNameUpdatedV2, + EServicePersonalDataUpdatedAfterPublishV2, EServiceRiskAnalysisAddedV1, EServiceRiskAnalysisAddedV2, EServiceRiskAnalysisDeletedV1, @@ -1539,6 +1540,7 @@ describe("database test", async () => { expect(retrievedEservice?.data).toEqual(updatedEService); expect(retrievedEservice?.metadata).toEqual({ version: 2 }); }); + it("EServiceSignalHubEnabled", async () => { const publishedDescriptor: Descriptor = { ...getMockDescriptor(), @@ -1575,6 +1577,7 @@ describe("database test", async () => { expect(retrievedEservice?.data).toEqual(updatedEService); expect(retrievedEservice?.metadata).toEqual({ version: 2 }); }); + it("EServiceSignalHubDisabled", async () => { const publishedDescriptor: Descriptor = { ...getMockDescriptor(), @@ -1611,6 +1614,43 @@ describe("database test", async () => { expect(retrievedEservice?.data).toEqual(updatedEService); expect(retrievedEservice?.metadata).toEqual({ version: 2 }); }); + + it("EServicePersonalDataUpdatedAfterPublish", async () => { + const publishedDescriptor: Descriptor = { + ...getMockDescriptor(), + interface: getMockDocument(), + state: descriptorState.published, + publishedAt: new Date(), + }; + const eservice: EService = { + ...mockEService, + descriptors: [publishedDescriptor], + }; + await catalogWriterService.upsertEService(mockEService, 1); + const updatedEService: EService = { + ...eservice, + personalData: true, + }; + const payload: EServicePersonalDataUpdatedAfterPublishV2 = { + eservice: toEServiceV2(updatedEService), + }; + const message: EServiceEventEnvelope = { + sequence_num: 1, + stream_id: mockEService.id, + version: 2, + type: "EServicePersonalDataUpdatedAfterPublish", + event_version: 2, + data: payload, + log_date: new Date(), + }; + await handleMessageV2(message, catalogWriterService); + const retrievedEservice = await catalogReadModelService.getEServiceById( + mockEService.id + ); + + expect(retrievedEservice?.data).toEqual(updatedEService); + expect(retrievedEservice?.metadata).toEqual({ version: 2 }); + }); }); }); From c9057f4cd937efbd7ef2f17fecda84d159610f39 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 22 Sep 2025 10:33:41 +0200 Subject: [PATCH 060/180] Increase outbound version --- packages/agreement-outbound-writer/package.json | 2 +- packages/catalog-outbound-writer/package.json | 2 +- packages/delegation-outbound-writer/package.json | 2 +- packages/eservice-template-outbound-writer/package.json | 2 +- packages/purpose-outbound-writer/package.json | 2 +- packages/tenant-outbound-writer/package.json | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/agreement-outbound-writer/package.json b/packages/agreement-outbound-writer/package.json index ad5d26942e..26bae961d6 100644 --- a/packages/agreement-outbound-writer/package.json +++ b/packages/agreement-outbound-writer/package.json @@ -28,7 +28,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.6", + "@pagopa/interop-outbound-models": "1.6.7", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/packages/catalog-outbound-writer/package.json b/packages/catalog-outbound-writer/package.json index 5e1b744b1c..bc99b2e3b5 100644 --- a/packages/catalog-outbound-writer/package.json +++ b/packages/catalog-outbound-writer/package.json @@ -28,7 +28,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.6", + "@pagopa/interop-outbound-models": "1.6.7", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/packages/delegation-outbound-writer/package.json b/packages/delegation-outbound-writer/package.json index 19d84c84b8..3169148594 100644 --- a/packages/delegation-outbound-writer/package.json +++ b/packages/delegation-outbound-writer/package.json @@ -27,7 +27,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.6", + "@pagopa/interop-outbound-models": "1.6.7", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/packages/eservice-template-outbound-writer/package.json b/packages/eservice-template-outbound-writer/package.json index 0445198b0f..c9ca892bfb 100644 --- a/packages/eservice-template-outbound-writer/package.json +++ b/packages/eservice-template-outbound-writer/package.json @@ -27,7 +27,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.6", + "@pagopa/interop-outbound-models": "1.6.7", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/packages/purpose-outbound-writer/package.json b/packages/purpose-outbound-writer/package.json index 17e9a4d6d1..ce74ec40d1 100644 --- a/packages/purpose-outbound-writer/package.json +++ b/packages/purpose-outbound-writer/package.json @@ -28,7 +28,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.6", + "@pagopa/interop-outbound-models": "1.6.7", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/packages/tenant-outbound-writer/package.json b/packages/tenant-outbound-writer/package.json index 2b9d649e28..dd0edf9b1a 100644 --- a/packages/tenant-outbound-writer/package.json +++ b/packages/tenant-outbound-writer/package.json @@ -28,7 +28,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.6", + "@pagopa/interop-outbound-models": "1.6.7", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", From f5659aec28e4a818ce46c4b9a4039a214486ba88 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 22 Sep 2025 10:35:15 +0200 Subject: [PATCH 061/180] Revert "Increase outbound version" This reverts commit c9057f4cd937efbd7ef2f17fecda84d159610f39. --- packages/agreement-outbound-writer/package.json | 2 +- packages/catalog-outbound-writer/package.json | 2 +- packages/delegation-outbound-writer/package.json | 2 +- packages/eservice-template-outbound-writer/package.json | 2 +- packages/purpose-outbound-writer/package.json | 2 +- packages/tenant-outbound-writer/package.json | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/agreement-outbound-writer/package.json b/packages/agreement-outbound-writer/package.json index 26bae961d6..ad5d26942e 100644 --- a/packages/agreement-outbound-writer/package.json +++ b/packages/agreement-outbound-writer/package.json @@ -28,7 +28,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.7", + "@pagopa/interop-outbound-models": "1.6.6", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/packages/catalog-outbound-writer/package.json b/packages/catalog-outbound-writer/package.json index bc99b2e3b5..5e1b744b1c 100644 --- a/packages/catalog-outbound-writer/package.json +++ b/packages/catalog-outbound-writer/package.json @@ -28,7 +28,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.7", + "@pagopa/interop-outbound-models": "1.6.6", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/packages/delegation-outbound-writer/package.json b/packages/delegation-outbound-writer/package.json index 3169148594..19d84c84b8 100644 --- a/packages/delegation-outbound-writer/package.json +++ b/packages/delegation-outbound-writer/package.json @@ -27,7 +27,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.7", + "@pagopa/interop-outbound-models": "1.6.6", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/packages/eservice-template-outbound-writer/package.json b/packages/eservice-template-outbound-writer/package.json index c9ca892bfb..0445198b0f 100644 --- a/packages/eservice-template-outbound-writer/package.json +++ b/packages/eservice-template-outbound-writer/package.json @@ -27,7 +27,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.7", + "@pagopa/interop-outbound-models": "1.6.6", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/packages/purpose-outbound-writer/package.json b/packages/purpose-outbound-writer/package.json index ce74ec40d1..17e9a4d6d1 100644 --- a/packages/purpose-outbound-writer/package.json +++ b/packages/purpose-outbound-writer/package.json @@ -28,7 +28,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.7", + "@pagopa/interop-outbound-models": "1.6.6", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/packages/tenant-outbound-writer/package.json b/packages/tenant-outbound-writer/package.json index dd0edf9b1a..2b9d649e28 100644 --- a/packages/tenant-outbound-writer/package.json +++ b/packages/tenant-outbound-writer/package.json @@ -28,7 +28,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.7", + "@pagopa/interop-outbound-models": "1.6.6", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", From 2e6fea8be2f4e25774c9dfa1c37fc2e785b9825f Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 22 Sep 2025 10:51:44 +0200 Subject: [PATCH 062/180] Reapply "Increase outbound version" This reverts commit f5659aec28e4a818ce46c4b9a4039a214486ba88. --- packages/agreement-outbound-writer/package.json | 2 +- packages/catalog-outbound-writer/package.json | 2 +- packages/delegation-outbound-writer/package.json | 2 +- packages/eservice-template-outbound-writer/package.json | 2 +- packages/purpose-outbound-writer/package.json | 2 +- packages/tenant-outbound-writer/package.json | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/agreement-outbound-writer/package.json b/packages/agreement-outbound-writer/package.json index ad5d26942e..26bae961d6 100644 --- a/packages/agreement-outbound-writer/package.json +++ b/packages/agreement-outbound-writer/package.json @@ -28,7 +28,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.6", + "@pagopa/interop-outbound-models": "1.6.7", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/packages/catalog-outbound-writer/package.json b/packages/catalog-outbound-writer/package.json index 5e1b744b1c..bc99b2e3b5 100644 --- a/packages/catalog-outbound-writer/package.json +++ b/packages/catalog-outbound-writer/package.json @@ -28,7 +28,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.6", + "@pagopa/interop-outbound-models": "1.6.7", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/packages/delegation-outbound-writer/package.json b/packages/delegation-outbound-writer/package.json index 19d84c84b8..3169148594 100644 --- a/packages/delegation-outbound-writer/package.json +++ b/packages/delegation-outbound-writer/package.json @@ -27,7 +27,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.6", + "@pagopa/interop-outbound-models": "1.6.7", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/packages/eservice-template-outbound-writer/package.json b/packages/eservice-template-outbound-writer/package.json index 0445198b0f..c9ca892bfb 100644 --- a/packages/eservice-template-outbound-writer/package.json +++ b/packages/eservice-template-outbound-writer/package.json @@ -27,7 +27,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.6", + "@pagopa/interop-outbound-models": "1.6.7", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/packages/purpose-outbound-writer/package.json b/packages/purpose-outbound-writer/package.json index 17e9a4d6d1..ce74ec40d1 100644 --- a/packages/purpose-outbound-writer/package.json +++ b/packages/purpose-outbound-writer/package.json @@ -28,7 +28,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.6", + "@pagopa/interop-outbound-models": "1.6.7", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/packages/tenant-outbound-writer/package.json b/packages/tenant-outbound-writer/package.json index 2b9d649e28..dd0edf9b1a 100644 --- a/packages/tenant-outbound-writer/package.json +++ b/packages/tenant-outbound-writer/package.json @@ -28,7 +28,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.6", + "@pagopa/interop-outbound-models": "1.6.7", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", From c3bdae1af30e5168be6227ad4e1f911ae3a3d5f0 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 22 Sep 2025 16:01:29 +0200 Subject: [PATCH 063/180] Add new event --- packages/models/proto/v2/eservice/events.proto | 4 ++++ packages/models/src/eservice/eserviceEvents.ts | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/packages/models/proto/v2/eservice/events.proto b/packages/models/proto/v2/eservice/events.proto index 85a6d92e25..20b306a5cb 100644 --- a/packages/models/proto/v2/eservice/events.proto +++ b/packages/models/proto/v2/eservice/events.proto @@ -214,3 +214,7 @@ message EServiceSignalHubDisabledV2 { message EServicePersonalDataUpdatedAfterPublishV2 { EServiceV2 eservice = 1; } + +message EServicePersonalDataUpdatedByTemplateUpdateV2 { + EServiceV2 eservice = 1; +} diff --git a/packages/models/src/eservice/eserviceEvents.ts b/packages/models/src/eservice/eserviceEvents.ts index 1c5e8cbd75..3a5a78d6c7 100644 --- a/packages/models/src/eservice/eserviceEvents.ts +++ b/packages/models/src/eservice/eserviceEvents.ts @@ -61,6 +61,7 @@ import { EServiceSignalHubEnabledV2, EServiceSignalHubDisabledV2, EServicePersonalDataUpdatedAfterPublishV2, + EServicePersonalDataUpdatedByTemplateUpdateV2, } from "../gen/v2/eservice/events.js"; export function catalogEventToBinaryData(event: EServiceEvent): Uint8Array { @@ -257,6 +258,9 @@ export function catalogEventToBinaryDataV2(event: EServiceEventV2): Uint8Array { .with({ type: "EServicePersonalDataUpdatedAfterPublish" }, ({ data }) => EServicePersonalDataUpdatedAfterPublishV2.toBinary(data) ) + .with({ type: "EServicePersonalDataUpdatedByTemplateUpdate" }, ({ data }) => + EServicePersonalDataUpdatedByTemplateUpdateV2.toBinary(data) + ) .exhaustive(); } @@ -547,6 +551,11 @@ export const EServiceEventV2 = z.discriminatedUnion("type", [ type: z.literal("EServicePersonalDataUpdatedAfterPublish"), data: protobufDecoder(EServicePersonalDataUpdatedAfterPublishV2), }), + z.object({ + event_version: z.literal(2), + type: z.literal("EServicePersonalDataUpdatedByTemplateUpdate"), + data: protobufDecoder(EServicePersonalDataUpdatedByTemplateUpdateV2), + }), ]); export type EServiceEventV2 = z.infer; From de477aaf140f05c4296ed4a83c8f82701e80c571 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 22 Sep 2025 16:01:53 +0200 Subject: [PATCH 064/180] Handle event in consumers --- .../src/converters/toOutboundEventV2.ts | 1 + packages/catalog-platformstate-writer/src/consumerServiceV2.ts | 1 + packages/catalog-readmodel-writer-sql/src/consumerServiceV2.ts | 1 + .../datalake-interface-exporter/src/interfaceExporterV2.ts | 1 + .../src/handlers/catalog/consumerServiceV2.ts | 3 ++- packages/events-signer/src/handlers/handleCatalogMessageV2.ts | 3 ++- .../src/handlers/eservices/handleEserviceEvent.ts | 3 ++- .../m2m-event-dispatcher/src/handlers/handleEServiceEvent.ts | 3 ++- packages/notification-email-sender/src/index.ts | 3 ++- .../models/catalog/catalogItemEventNotificationConverter.ts | 1 + .../src/models/catalog/catalogItemEventNotificationMessage.ts | 1 + 11 files changed, 16 insertions(+), 5 deletions(-) diff --git a/packages/catalog-outbound-writer/src/converters/toOutboundEventV2.ts b/packages/catalog-outbound-writer/src/converters/toOutboundEventV2.ts index d93b4df79f..e3ec5f2fdd 100644 --- a/packages/catalog-outbound-writer/src/converters/toOutboundEventV2.ts +++ b/packages/catalog-outbound-writer/src/converters/toOutboundEventV2.ts @@ -98,6 +98,7 @@ export function toOutboundEventV2( { type: "EServiceSignalHubEnabled" }, { type: "EServiceSignalHubDisabled" }, { type: "EServicePersonalDataUpdatedAfterPublish" }, + { type: "EServicePersonalDataUpdatedByTemplateUpdate" }, (msg) => ({ event_version: msg.event_version, type: msg.type, diff --git a/packages/catalog-platformstate-writer/src/consumerServiceV2.ts b/packages/catalog-platformstate-writer/src/consumerServiceV2.ts index 658538b612..46ff6ac74d 100644 --- a/packages/catalog-platformstate-writer/src/consumerServiceV2.ts +++ b/packages/catalog-platformstate-writer/src/consumerServiceV2.ts @@ -304,6 +304,7 @@ export async function handleMessageV2( { type: "EServiceSignalHubEnabled" }, { type: "EServiceSignalHubDisabled" }, { type: "EServicePersonalDataUpdatedAfterPublish" }, + { type: "EServicePersonalDataUpdatedByTemplateUpdate" }, () => Promise.resolve() ) .exhaustive(); diff --git a/packages/catalog-readmodel-writer-sql/src/consumerServiceV2.ts b/packages/catalog-readmodel-writer-sql/src/consumerServiceV2.ts index 5fbb0ade53..3a1e692ccb 100644 --- a/packages/catalog-readmodel-writer-sql/src/consumerServiceV2.ts +++ b/packages/catalog-readmodel-writer-sql/src/consumerServiceV2.ts @@ -60,6 +60,7 @@ export async function handleMessageV2( { type: "EServiceSignalHubEnabled" }, { type: "EServiceSignalHubDisabled" }, { type: "EServicePersonalDataUpdatedAfterPublish" }, + { type: "EServicePersonalDataUpdatedByTemplateUpdate" }, async (message) => { const eservice = message.data.eservice; if (!eservice) { diff --git a/packages/datalake-interface-exporter/src/interfaceExporterV2.ts b/packages/datalake-interface-exporter/src/interfaceExporterV2.ts index 44b62f79fd..14df05fda2 100644 --- a/packages/datalake-interface-exporter/src/interfaceExporterV2.ts +++ b/packages/datalake-interface-exporter/src/interfaceExporterV2.ts @@ -75,6 +75,7 @@ export async function exportInterfaceV2( { type: "EServiceSignalHubEnabled" }, { type: "EServiceSignalHubDisabled" }, { type: "EServicePersonalDataUpdatedAfterPublish" }, + { type: "EServicePersonalDataUpdatedByTemplateUpdate" }, () => undefined ) .exhaustive(); diff --git a/packages/domains-analytics-writer/src/handlers/catalog/consumerServiceV2.ts b/packages/domains-analytics-writer/src/handlers/catalog/consumerServiceV2.ts index f4afb62d5e..dc1aee591d 100644 --- a/packages/domains-analytics-writer/src/handlers/catalog/consumerServiceV2.ts +++ b/packages/domains-analytics-writer/src/handlers/catalog/consumerServiceV2.ts @@ -78,7 +78,8 @@ export async function handleCatalogMessageV2( "EServiceDraftDescriptorDeleted", "EServiceSignalHubEnabled", "EServiceSignalHubDisabled", - "EServicePersonalDataUpdatedAfterPublish" + "EServicePersonalDataUpdatedAfterPublish", + "EServicePersonalDataUpdatedByTemplateUpdate" ), }, (msg) => { diff --git a/packages/events-signer/src/handlers/handleCatalogMessageV2.ts b/packages/events-signer/src/handlers/handleCatalogMessageV2.ts index 7c068c5610..849616fb2e 100644 --- a/packages/events-signer/src/handlers/handleCatalogMessageV2.ts +++ b/packages/events-signer/src/handlers/handleCatalogMessageV2.ts @@ -103,7 +103,8 @@ export const handleCatalogMessageV2 = async ( "EServiceDescriptorDocumentDeletedByTemplateUpdate", "EServiceSignalHubEnabled", "EServiceSignalHubDisabled", - "EServicePersonalDataUpdatedAfterPublish" + "EServicePersonalDataUpdatedAfterPublish", + "EServicePersonalDataUpdatedByTemplateUpdate" ), }, (event) => { diff --git a/packages/in-app-notification-dispatcher/src/handlers/eservices/handleEserviceEvent.ts b/packages/in-app-notification-dispatcher/src/handlers/eservices/handleEserviceEvent.ts index 62b1197214..01f46bced0 100644 --- a/packages/in-app-notification-dispatcher/src/handlers/eservices/handleEserviceEvent.ts +++ b/packages/in-app-notification-dispatcher/src/handlers/eservices/handleEserviceEvent.ts @@ -92,7 +92,8 @@ export async function handleEServiceEvent( "EServiceIsClientAccessDelegableDisabled", "EServiceSignalHubEnabled", "EServiceSignalHubDisabled", - "EServicePersonalDataUpdatedAfterPublish" + "EServicePersonalDataUpdatedAfterPublish", + "EServicePersonalDataUpdatedByTemplateUpdate" ), }, () => { diff --git a/packages/m2m-event-dispatcher/src/handlers/handleEServiceEvent.ts b/packages/m2m-event-dispatcher/src/handlers/handleEServiceEvent.ts index ba7f5f1cdd..f02feda646 100644 --- a/packages/m2m-event-dispatcher/src/handlers/handleEServiceEvent.ts +++ b/packages/m2m-event-dispatcher/src/handlers/handleEServiceEvent.ts @@ -55,7 +55,8 @@ export async function handleEServiceEvent( "EServiceDescriptorDocumentUpdatedByTemplateUpdate", "EServiceSignalHubEnabled", "EServiceSignalHubDisabled", - "EServicePersonalDataUpdatedAfterPublish" + "EServicePersonalDataUpdatedAfterPublish", + "EServicePersonalDataUpdatedByTemplateUpdate" ), }, () => Promise.resolve(void 0) diff --git a/packages/notification-email-sender/src/index.ts b/packages/notification-email-sender/src/index.ts index ca6eec9bc9..e85d24f0e3 100644 --- a/packages/notification-email-sender/src/index.ts +++ b/packages/notification-email-sender/src/index.ts @@ -162,7 +162,8 @@ export async function handleCatalogMessage( "EServiceDescriptorDocumentUpdatedByTemplateUpdate", "EServiceSignalHubEnabled", "EServiceSignalHubDisabled", - "EServicePersonalDataUpdatedAfterPublish" + "EServicePersonalDataUpdatedAfterPublish", + "EServicePersonalDataUpdatedByTemplateUpdate" ), }, () => { diff --git a/packages/notifier-seeder/src/models/catalog/catalogItemEventNotificationConverter.ts b/packages/notifier-seeder/src/models/catalog/catalogItemEventNotificationConverter.ts index d20b8386de..ff4435bf9a 100644 --- a/packages/notifier-seeder/src/models/catalog/catalogItemEventNotificationConverter.ts +++ b/packages/notifier-seeder/src/models/catalog/catalogItemEventNotificationConverter.ts @@ -101,6 +101,7 @@ export const toCatalogItemEventNotification = ( { type: "EServiceSignalHubDisabled" }, // CatalogItemV1UpdatedV1 { type: "EServiceNameUpdatedByTemplateUpdate" }, { type: "EServicePersonalDataUpdatedAfterPublish" }, + { type: "EServicePersonalDataUpdatedByTemplateUpdate" }, (e): CatalogItemNotification => ({ catalogItem: getCatalogItem(e), }) diff --git a/packages/notifier-seeder/src/models/catalog/catalogItemEventNotificationMessage.ts b/packages/notifier-seeder/src/models/catalog/catalogItemEventNotificationMessage.ts index 8d8207b251..96239a3a96 100644 --- a/packages/notifier-seeder/src/models/catalog/catalogItemEventNotificationMessage.ts +++ b/packages/notifier-seeder/src/models/catalog/catalogItemEventNotificationMessage.ts @@ -22,6 +22,7 @@ export const eventV2TypeMapper = ( "EServiceSignalHubEnabled", "EServiceSignalHubDisabled", "EServicePersonalDataUpdatedAfterPublish", + "EServicePersonalDataUpdatedByTemplateUpdate", () => "catalog_item_updated" ) .with( From f0cc7f597d55a59f474b96cfa0160daa82d468a1 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 22 Sep 2025 16:01:59 +0200 Subject: [PATCH 065/180] Update pnpm-lock file --- pnpm-lock.yaml | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 293a448dc7..71f3c82517 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -40,8 +40,8 @@ importers: packages/agreement-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.6 - version: 1.6.6 + specifier: 1.6.7 + version: 1.6.7 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -1184,8 +1184,8 @@ importers: packages/catalog-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.6 - version: 1.6.6 + specifier: 1.6.7 + version: 1.6.7 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -2118,8 +2118,8 @@ importers: packages/delegation-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.6 - version: 1.6.6 + specifier: 1.6.7 + version: 1.6.7 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -2694,8 +2694,8 @@ importers: packages/eservice-template-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.6 - version: 1.6.6 + specifier: 1.6.7 + version: 1.6.7 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -4444,8 +4444,8 @@ importers: packages/purpose-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.6 - version: 1.6.6 + specifier: 1.6.7 + version: 1.6.7 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -5140,8 +5140,8 @@ importers: packages/tenant-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.6 - version: 1.6.6 + specifier: 1.6.7 + version: 1.6.7 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -6850,8 +6850,8 @@ packages: '@pagopa/eslint-config@3.0.0': resolution: {integrity: sha512-eYIPdiuYRbRPR5k0OuteRNqYb0Z2nfJ/lZohejB7ylfBeSDWwkaV8Z19AXP4RymE6oEesyPDZ6i0yNaE9tQrHw==} - '@pagopa/interop-outbound-models@1.6.6': - resolution: {integrity: sha512-TPoI/RPRl5wFH1ui6eK4KdAEC+gq4tN2svifSSBLQBdQB7FccxO1kYBs+0ytCRJp8u/T48EbsT+d9wyYvlwHfw==} + '@pagopa/interop-outbound-models@1.6.7': + resolution: {integrity: sha512-SHdILvJBReRN5tbE+8U2A9HJHo5EXgckQ14Y0GH0NWwjfaXESx+XV8ItbrUISt0jH65V58SB8tBPSfwjOdp2Qw==} '@protobuf-ts/plugin-framework@2.9.4': resolution: {integrity: sha512-9nuX1kjdMliv+Pes8dQCKyVhjKgNNfwxVHg+tx3fLXSfZZRcUHMc1PMwB9/vTvc6gBKt9QGz5ERqSqZc0++E9A==} @@ -13855,7 +13855,7 @@ snapshots: - tsutils - typescript - '@pagopa/interop-outbound-models@1.6.6': + '@pagopa/interop-outbound-models@1.6.7': dependencies: '@protobuf-ts/runtime': 2.9.4 ts-pattern: 5.2.0 From 1ecacbbe358cc9c7959ea5394d7b2869ca7a9575 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 22 Sep 2025 16:50:01 +0200 Subject: [PATCH 066/180] Add template event --- .../models/proto/v2/eservice-template/events.proto | 4 ++++ .../src/eservice-template/eserviceTemplateEvents.ts | 11 +++++++++++ 2 files changed, 15 insertions(+) diff --git a/packages/models/proto/v2/eservice-template/events.proto b/packages/models/proto/v2/eservice-template/events.proto index 71142fdfb8..ea4730d469 100644 --- a/packages/models/proto/v2/eservice-template/events.proto +++ b/packages/models/proto/v2/eservice-template/events.proto @@ -120,3 +120,7 @@ message EServiceTemplateVersionActivatedV2 { string eserviceTemplateVersionId = 1; EServiceTemplateV2 eserviceTemplate = 2; } + +message EServiceTemplatePersonalDataUpdatedAfterPublishV2 { + EServiceTemplateV2 eserviceTemplate = 1; +} diff --git a/packages/models/src/eservice-template/eserviceTemplateEvents.ts b/packages/models/src/eservice-template/eserviceTemplateEvents.ts index f1b1c2ff62..85cf6ea3d3 100644 --- a/packages/models/src/eservice-template/eserviceTemplateEvents.ts +++ b/packages/models/src/eservice-template/eserviceTemplateEvents.ts @@ -25,6 +25,7 @@ import { EServiceTemplateVersionInterfaceUpdatedV2, EServiceTemplateVersionPublishedV2, EServiceTemplateVersionQuotasUpdatedV2, + EServiceTemplatePersonalDataUpdatedAfterPublishV2, } from "../gen/v2/eservice-template/events.js"; import { protobufDecoder } from "../protobuf/protobuf.js"; import { EventEnvelope } from "../events/events.js"; @@ -145,6 +146,11 @@ export const EServiceTemplateEventV2 = z.discriminatedUnion("type", [ type: z.literal("EServiceTemplateVersionActivated"), data: protobufDecoder(EServiceTemplateVersionActivatedV2), }), + z.object({ + event_version: z.literal(2), + type: z.literal("EServiceTemplatePersonalDataUpdatedAfterPublish"), + data: protobufDecoder(EServiceTemplatePersonalDataUpdatedAfterPublishV2), + }), ]); export type EServiceTemplateEventV2 = z.infer; @@ -222,6 +228,11 @@ export function eserviceTemplateEventToBinaryDataV2( .with({ type: "EServiceTemplateVersionQuotasUpdated" }, ({ data }) => EServiceTemplateVersionQuotasUpdatedV2.toBinary(data) ) + .with( + { type: "EServiceTemplatePersonalDataUpdatedAfterPublish" }, + ({ data }) => + EServiceTemplatePersonalDataUpdatedAfterPublishV2.toBinary(data) + ) .exhaustive(); } From 1a510a6cae7ce3648a6a3226d744511c8cddb0be Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 22 Sep 2025 16:50:11 +0200 Subject: [PATCH 067/180] Handle template event --- .../src/handlers/eservice-template/consumerServiceV2.ts | 3 ++- .../eserviceTemplateInstancesUpdaterConsumerServiceV2.ts | 8 ++++++++ .../src/converters/toOutboundEventV2.ts | 1 + .../src/consumerServiceV2.ts | 1 + .../src/handlers/handleEServiceTemplateEvent.ts | 3 ++- 5 files changed, 14 insertions(+), 2 deletions(-) diff --git a/packages/domains-analytics-writer/src/handlers/eservice-template/consumerServiceV2.ts b/packages/domains-analytics-writer/src/handlers/eservice-template/consumerServiceV2.ts index 69bb33beaf..f65e736a9c 100644 --- a/packages/domains-analytics-writer/src/handlers/eservice-template/consumerServiceV2.ts +++ b/packages/domains-analytics-writer/src/handlers/eservice-template/consumerServiceV2.ts @@ -52,7 +52,8 @@ export async function handleEserviceTemplateMessageV2( "EServiceTemplateDraftVersionDeleted", "EServiceTemplateVersionInterfaceDeleted", "EServiceTemplateVersionDocumentDeleted", - "EServiceTemplateRiskAnalysisDeleted" + "EServiceTemplateRiskAnalysisDeleted", + "EServiceTemplatePersonalDataUpdatedAfterPublish" ), }, (msg) => { diff --git a/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts b/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts index 016b4e8d76..ac95294973 100644 --- a/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts +++ b/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts @@ -328,6 +328,14 @@ export async function handleMessageV2({ deleteEServiceTemplateInstanceDescriptorDocument ); }) + .with( + { + type: "EServiceTemplatePersonalDataUpdatedAfterPublish", + }, + () => { + // TODO + } + ) .with( { type: "EServiceTemplateAdded" }, { type: "EServiceTemplateIntendedTargetUpdated" }, diff --git a/packages/eservice-template-outbound-writer/src/converters/toOutboundEventV2.ts b/packages/eservice-template-outbound-writer/src/converters/toOutboundEventV2.ts index c69315b3c9..3cb745043c 100644 --- a/packages/eservice-template-outbound-writer/src/converters/toOutboundEventV2.ts +++ b/packages/eservice-template-outbound-writer/src/converters/toOutboundEventV2.ts @@ -55,6 +55,7 @@ export function toOutboundEventV2( { type: "EServiceTemplateDeleted" }, { type: "EServiceTemplateIntendedTargetUpdated" }, { type: "EServiceTemplateDescriptionUpdated" }, + { type: "EServiceTemplatePersonalDataUpdatedAfterPublish" }, (msg) => ({ event_version: msg.event_version, type: msg.type, diff --git a/packages/eservice-template-readmodel-writer-sql/src/consumerServiceV2.ts b/packages/eservice-template-readmodel-writer-sql/src/consumerServiceV2.ts index 39579021c4..467abaff60 100644 --- a/packages/eservice-template-readmodel-writer-sql/src/consumerServiceV2.ts +++ b/packages/eservice-template-readmodel-writer-sql/src/consumerServiceV2.ts @@ -49,6 +49,7 @@ export async function handleMessageV2( { type: "EServiceTemplateVersionInterfaceUpdated" }, { type: "EServiceTemplateVersionPublished" }, { type: "EServiceTemplateVersionQuotasUpdated" }, + { type: "EServiceTemplatePersonalDataUpdatedAfterPublish" }, async (message) => { await eserviceTemplateWriterService.upsertEServiceTemplate( fromEServiceTemplateV2(eserviceTemplate), diff --git a/packages/m2m-event-dispatcher/src/handlers/handleEServiceTemplateEvent.ts b/packages/m2m-event-dispatcher/src/handlers/handleEServiceTemplateEvent.ts index 54f8707f7a..23878c4717 100644 --- a/packages/m2m-event-dispatcher/src/handlers/handleEServiceTemplateEvent.ts +++ b/packages/m2m-event-dispatcher/src/handlers/handleEServiceTemplateEvent.ts @@ -36,7 +36,8 @@ export async function handleEServiceTemplateEvent( "EServiceTemplateVersionInterfaceDeleted", "EServiceTemplateVersionInterfaceUpdated", "EServiceTemplateVersionPublished", - "EServiceTemplateVersionQuotasUpdated" + "EServiceTemplateVersionQuotasUpdated", + "EServiceTemplatePersonalDataUpdatedAfterPublish" ), }, () => Promise.resolve(void 0) From a09494138dbe4fa9fbee80a461173420a2b180b5 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 22 Sep 2025 17:09:51 +0200 Subject: [PATCH 068/180] Update pnpm-lock file --- pnpm-lock.yaml | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 293a448dc7..71f3c82517 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -40,8 +40,8 @@ importers: packages/agreement-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.6 - version: 1.6.6 + specifier: 1.6.7 + version: 1.6.7 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -1184,8 +1184,8 @@ importers: packages/catalog-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.6 - version: 1.6.6 + specifier: 1.6.7 + version: 1.6.7 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -2118,8 +2118,8 @@ importers: packages/delegation-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.6 - version: 1.6.6 + specifier: 1.6.7 + version: 1.6.7 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -2694,8 +2694,8 @@ importers: packages/eservice-template-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.6 - version: 1.6.6 + specifier: 1.6.7 + version: 1.6.7 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -4444,8 +4444,8 @@ importers: packages/purpose-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.6 - version: 1.6.6 + specifier: 1.6.7 + version: 1.6.7 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -5140,8 +5140,8 @@ importers: packages/tenant-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.6 - version: 1.6.6 + specifier: 1.6.7 + version: 1.6.7 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -6850,8 +6850,8 @@ packages: '@pagopa/eslint-config@3.0.0': resolution: {integrity: sha512-eYIPdiuYRbRPR5k0OuteRNqYb0Z2nfJ/lZohejB7ylfBeSDWwkaV8Z19AXP4RymE6oEesyPDZ6i0yNaE9tQrHw==} - '@pagopa/interop-outbound-models@1.6.6': - resolution: {integrity: sha512-TPoI/RPRl5wFH1ui6eK4KdAEC+gq4tN2svifSSBLQBdQB7FccxO1kYBs+0ytCRJp8u/T48EbsT+d9wyYvlwHfw==} + '@pagopa/interop-outbound-models@1.6.7': + resolution: {integrity: sha512-SHdILvJBReRN5tbE+8U2A9HJHo5EXgckQ14Y0GH0NWwjfaXESx+XV8ItbrUISt0jH65V58SB8tBPSfwjOdp2Qw==} '@protobuf-ts/plugin-framework@2.9.4': resolution: {integrity: sha512-9nuX1kjdMliv+Pes8dQCKyVhjKgNNfwxVHg+tx3fLXSfZZRcUHMc1PMwB9/vTvc6gBKt9QGz5ERqSqZc0++E9A==} @@ -13855,7 +13855,7 @@ snapshots: - tsutils - typescript - '@pagopa/interop-outbound-models@1.6.6': + '@pagopa/interop-outbound-models@1.6.7': dependencies: '@protobuf-ts/runtime': 2.9.4 ts-pattern: 5.2.0 From 9ec78c4aad4d128a2cc84d628f74a3b3f86c9707 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 22 Sep 2025 17:31:54 +0200 Subject: [PATCH 069/180] Add api spec for internal endpoint --- packages/api-clients/open-api/catalogApi.yml | 37 ++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/packages/api-clients/open-api/catalogApi.yml b/packages/api-clients/open-api/catalogApi.yml index cd7715998b..56f489496f 100644 --- a/packages/api-clients/open-api/catalogApi.yml +++ b/packages/api-clients/open-api/catalogApi.yml @@ -2277,6 +2277,43 @@ paths: application/problem+json: schema: $ref: "#/components/schemas/Problem" + /internal/templates/eservices/{eServiceId}/personalData/set: + post: + parameters: + - $ref: "#/components/parameters/CorrelationIdHeader" + - name: eServiceId + in: path + description: the eservice id + required: true + schema: + type: string + format: uuid + tags: + - process + requestBody: + description: A payload containing a boolean that describes the personalData flag + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/EServicePersonalDataUpdateSeed" + operationId: setTemplateInstancePersonalData + description: Update the personalData flag of a template instance after a template update + responses: + "204": + description: E-Service personalData updated + "404": + description: E-Service Not Found + content: + application/problem+json: + schema: + $ref: "#/components/schemas/Problem" + "403": + description: Forbidden + content: + application/problem+json: + schema: + $ref: "#/components/schemas/Problem" /internal/templates/eservices/{eServiceId}/descriptors/{descriptorId}/voucherLifespan/update: post: parameters: From 2480b70940790be551305dd06d3ba34381a814ae Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 22 Sep 2025 17:32:15 +0200 Subject: [PATCH 070/180] Call internal endpoint from instances-updater --- ...mplateInstancesUpdaterConsumerServiceV2.ts | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts b/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts index ac95294973..30ce5e793f 100644 --- a/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts +++ b/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts @@ -332,8 +332,37 @@ export async function handleMessageV2({ { type: "EServiceTemplatePersonalDataUpdatedAfterPublish", }, - () => { - // TODO + async (msg) => { + const personalData = getTemplateFromEvent(msg).personalData; + + if (personalData === undefined) { + throw missingKafkaMessageDataError( + "eserviceTemplate.personalData", + "EServiceTemplatePersonalDataUpdatedAfterPublish" + ); + } + const updateTemplateInstancePersonalData = async ( + instance: EService, + headers: InteropHeaders + ): Promise => { + await catalogProcess.client.setTemplateInstancePersonalData( + { personalData }, + { + params: { + eServiceId: instance.id, + }, + headers, + } + ); + }; + + await commitUpdateToTemplateInstances( + msg, + refreshableToken, + correlationId, + readModelService, + updateTemplateInstancePersonalData + ); } ) .with( From fb38a3b91c3844193c16c41ff5265ac055fdb660 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 22 Sep 2025 17:41:27 +0200 Subject: [PATCH 071/180] Implement endpoint --- .../src/model/domain/toEvent.ts | 17 +++++++++++++ .../src/routers/EServiceRouter.ts | 25 +++++++++++++++++++ .../src/services/catalogService.ts | 25 +++++++++++++++++++ .../src/utilities/errorMappers.ts | 8 ++++++ 4 files changed, 75 insertions(+) diff --git a/packages/catalog-process/src/model/domain/toEvent.ts b/packages/catalog-process/src/model/domain/toEvent.ts index f0d64e74a4..4c2e66dad5 100644 --- a/packages/catalog-process/src/model/domain/toEvent.ts +++ b/packages/catalog-process/src/model/domain/toEvent.ts @@ -702,6 +702,23 @@ export const toCreateEventEServiceDescriptionUpdatedByTemplateUpdate = ( correlationId, }); +export const toCreateEventEServicePersonalDataUpdatedByTemplateUpdate = ( + version: number, + eservice: EService, + correlationId: CorrelationId +): CreateEvent => ({ + streamId: eservice.id, + version, + event: { + type: "EServicePersonalDataUpdatedByTemplateUpdate", + event_version: 2, + data: { + eservice: toEServiceV2(eservice), + }, + }, + correlationId, +}); + export const toCreateEventEServiceDescriptorQuotasUpdatedByTemplateUpdate = ( streamId: string, version: number, diff --git a/packages/catalog-process/src/routers/EServiceRouter.ts b/packages/catalog-process/src/routers/EServiceRouter.ts index 3836d98f3b..fdbdbc38b0 100644 --- a/packages/catalog-process/src/routers/EServiceRouter.ts +++ b/packages/catalog-process/src/routers/EServiceRouter.ts @@ -75,6 +75,7 @@ import { updateEServiceSignalhubFlagErrorMapper, documentListErrorMapper, updateEServicePersonalDataErrorMapper, + updateTemplateInstancePersonalDataErrorMapper, } from "../utilities/errorMappers.js"; import { CatalogService } from "../services/catalogService.js"; import { config } from "../config/config.js"; @@ -1234,6 +1235,30 @@ const eservicesRouter = ( } } ) + .post( + "/internal/templates/eservices/:eServiceId/personalData/set", + async (req, res) => { + const ctx = fromAppContext(req.ctx); + + try { + validateAuthorization(ctx, [INTERNAL_ROLE]); + + await catalogService.internalUpdateTemplateInstancePersonalData( + unsafeBrandId(req.params.eServiceId), + req.body.personalData, + ctx + ); + return res.status(204).send(); + } catch (error) { + const errorRes = makeApiProblem( + error, + updateTemplateInstancePersonalDataErrorMapper, + ctx + ); + return res.status(errorRes.status).send(errorRes); + } + } + ) .post( "/internal/templates/eservices/:eServiceId/descriptors/:descriptorId/voucherLifespan/update", async (req, res) => { diff --git a/packages/catalog-process/src/services/catalogService.ts b/packages/catalog-process/src/services/catalogService.ts index 9f8ef08f2e..700b97045d 100644 --- a/packages/catalog-process/src/services/catalogService.ts +++ b/packages/catalog-process/src/services/catalogService.ts @@ -147,6 +147,7 @@ import { toCreateEventEServiceSignalhubFlagEnabled, toCreateEventEServiceSignalhubFlagDisabled, toCreateEventEServicePersonalDataUpdatedAfterPublish, + toCreateEventEServicePersonalDataUpdatedByTemplateUpdate, } from "../model/domain/toEvent.js"; import { getLatestDescriptor, @@ -2918,6 +2919,30 @@ export function catalogServiceBuilder( ) ); }, + async internalUpdateTemplateInstancePersonalData( + eserviceId: EServiceId, + personalData: boolean, + { correlationId, logger }: WithLogger + ): Promise { + logger.info(`Internal updating EService ${eserviceId} personalData`); + const eservice = await retrieveEService(eserviceId, readModelService); + + if (eservice.data.personalData !== undefined) { + throw eservicePersonalDataCanOnlyBeSetOnce(eserviceId); + } + + const updatedEservice: EService = { + ...eservice.data, + personalData, + }; + await repository.createEvent( + toCreateEventEServicePersonalDataUpdatedByTemplateUpdate( + eservice.metadata.version, + updatedEservice, + correlationId + ) + ); + }, async internalUpdateTemplateInstanceDescriptorVoucherLifespan( eserviceId: EServiceId, descriptorId: DescriptorId, diff --git a/packages/catalog-process/src/utilities/errorMappers.ts b/packages/catalog-process/src/utilities/errorMappers.ts index c4872b13a5..4bc0208648 100644 --- a/packages/catalog-process/src/utilities/errorMappers.ts +++ b/packages/catalog-process/src/utilities/errorMappers.ts @@ -555,6 +555,14 @@ export const updateTemplateInstanceDescriptionErrorMapper = ( .with("eServiceNotFound", () => HTTP_STATUS_NOT_FOUND) .otherwise(() => HTTP_STATUS_INTERNAL_SERVER_ERROR); +export const updateTemplateInstancePersonalDataErrorMapper = ( + error: ApiError +): number => + match(error.code) + .with("eServiceNotFound", () => HTTP_STATUS_NOT_FOUND) + .with("eservicePersonalDataCanOnlyBeSetOnce", () => HTTP_STATUS_CONFLICT) + .otherwise(() => HTTP_STATUS_INTERNAL_SERVER_ERROR); + export const updateTemplateInstanceDescriptorVoucherLifespanErrorMapper = ( error: ApiError ): number => From 13c63a667f48ce42704f6ca1dcb34bb58aeb118e Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Tue, 23 Sep 2025 14:03:55 +0200 Subject: [PATCH 072/180] feat(eservice-template): add personalData check on publishEServiceTemplateVersion --- .../src/model/domain/errors.ts | 12 +++++++ .../src/services/eserviceTemplateService.ts | 11 ++++++ .../src/utilities/errorMappers.ts | 1 + .../publishEServiceTemplateVersion.test.ts | 8 +++++ .../publishEServiceTemplateVersion.test.ts | 35 +++++++++++++++++++ 5 files changed, 67 insertions(+) diff --git a/packages/eservice-template-process/src/model/domain/errors.ts b/packages/eservice-template-process/src/model/domain/errors.ts index 93a939c158..c7c65c747f 100644 --- a/packages/eservice-template-process/src/model/domain/errors.ts +++ b/packages/eservice-template-process/src/model/domain/errors.ts @@ -34,6 +34,7 @@ export const errorCodes = { eserviceTemplateDocumentNotFound: "0025", riskAnalysisNotFound: "0026", attributeDuplicatedInGroup: "0027", + eserviceTemplatePersonalDataMustBeSet: "0028", }; export type ErrorCodes = keyof typeof errorCodes; @@ -298,3 +299,14 @@ export function attributeDuplicatedInGroup( title: "Duplicated attribute in group", }); } + +export function eserviceTemplatePersonalDataMustBeSet( + eserviceTemplateId: EServiceTemplateId, + eserviceTemplateVersionId: EServiceTemplateVersionId +): ApiError { + return new ApiError({ + detail: `Template version ${eserviceTemplateVersionId} in eserviceTemplate ${eserviceTemplateId} can't be published because personalData flag must be set`, + code: "eserviceTemplatePersonalDataMustBeSet", + title: "EService Template personalData must be set before publication", + }); +} diff --git a/packages/eservice-template-process/src/services/eserviceTemplateService.ts b/packages/eservice-template-process/src/services/eserviceTemplateService.ts index 2c62f6102c..c0132436f7 100644 --- a/packages/eservice-template-process/src/services/eserviceTemplateService.ts +++ b/packages/eservice-template-process/src/services/eserviceTemplateService.ts @@ -49,6 +49,7 @@ import { instanceNameConflict, notValidEServiceTemplateVersionState, attributeDuplicatedInGroup, + eserviceTemplatePersonalDataMustBeSet, } from "../model/domain/errors.js"; import { versionAttributeGroupSupersetMissingInAttributesSeed, @@ -526,6 +527,16 @@ export function eserviceTemplateServiceBuilder( assertRiskAnalysisIsValidForPublication(eserviceTemplate.data); } + if ( + config.featureFlagEservicePersonalData && + eserviceTemplate.data.personalData === undefined + ) { + throw eserviceTemplatePersonalDataMustBeSet( + eserviceTemplateId, + eserviceTemplateVersionId + ); + } + const publishedTemplate: EServiceTemplate = { ...eserviceTemplate.data, versions: eserviceTemplate.data.versions.map((v) => diff --git a/packages/eservice-template-process/src/utilities/errorMappers.ts b/packages/eservice-template-process/src/utilities/errorMappers.ts index bc31fac5ff..744ba2fb4e 100644 --- a/packages/eservice-template-process/src/utilities/errorMappers.ts +++ b/packages/eservice-template-process/src/utilities/errorMappers.ts @@ -60,6 +60,7 @@ export const publishEServiceTemplateVersionErrorMapper = ( .with( "notValidEServiceTemplateVersionState", "riskAnalysisValidationFailed", + "eserviceTemplatePersonalDataMustBeSet", () => HTTP_STATUS_BAD_REQUEST ) .with("operationForbidden", () => HTTP_STATUS_FORBIDDEN) diff --git a/packages/eservice-template-process/test/api/publishEServiceTemplateVersion.test.ts b/packages/eservice-template-process/test/api/publishEServiceTemplateVersion.test.ts index e8c80d91e5..b75b21301e 100644 --- a/packages/eservice-template-process/test/api/publishEServiceTemplateVersion.test.ts +++ b/packages/eservice-template-process/test/api/publishEServiceTemplateVersion.test.ts @@ -20,6 +20,7 @@ import request from "supertest"; import { api, eserviceTemplateService } from "../vitest.api.setup.js"; import { eserviceTemplateNotFound, + eserviceTemplatePersonalDataMustBeSet, eserviceTemplateVersionNotFound, missingTemplateVersionInterface, notValidEServiceTemplateVersionState, @@ -98,6 +99,13 @@ describe("API POST /templates/:templateId/versions/:templateVersionId/publish", ), expectedStatus: 400, }, + { + error: eserviceTemplatePersonalDataMustBeSet( + mockEserviceTemplate.id, + mockEserviceTemplate.versions[0].id + ), + expectedStatus: 400, + }, { error: riskAnalysisValidationFailed([ new RiskAnalysisValidationIssue({ diff --git a/packages/eservice-template-process/test/integration/publishEServiceTemplateVersion.test.ts b/packages/eservice-template-process/test/integration/publishEServiceTemplateVersion.test.ts index 1a25ee3f03..1134f4a4b1 100644 --- a/packages/eservice-template-process/test/integration/publishEServiceTemplateVersion.test.ts +++ b/packages/eservice-template-process/test/integration/publishEServiceTemplateVersion.test.ts @@ -28,6 +28,7 @@ import { import { expect, describe, it, afterAll, vi, beforeAll } from "vitest"; import { eserviceTemplateNotFound, + eserviceTemplatePersonalDataMustBeSet, eserviceTemplateVersionNotFound, missingRiskAnalysis, missingTemplateVersionInterface, @@ -80,6 +81,7 @@ describe("publishEServiceTemplateVersion", () => { eserviceTemplateVersion, newerEServiceTemplateVersion, ], + personalData: false, }; await addOneTenant({ @@ -360,6 +362,7 @@ describe("publishEServiceTemplateVersion", () => { riskAnalysis: [], creatorId: tenant.id, mode: eserviceMode.deliver, + personalData: false, }; await addOneTenant(tenant); @@ -405,6 +408,7 @@ describe("publishEServiceTemplateVersion", () => { riskAnalysis: [invalidRiskAnalysis], creatorId: tenant.id, mode: eserviceMode.deliver, + personalData: false, }; await addOneTenant(tenant); @@ -420,4 +424,35 @@ describe("publishEServiceTemplateVersion", () => { ) ).equal(undefined); }); + + it("should throw eserviceTemplatePersonalDataMustBeSet if the template has personalData undefined", async () => { + const eserviceTemplateVersion: EServiceTemplateVersion = { + ...getMockEServiceTemplateVersion(), + state: descriptorState.draft, + interface: getMockDocument(), + }; + + const eserviceTemplate: EServiceTemplate = { + ...getMockEServiceTemplate(), + versions: [eserviceTemplateVersion], + personalData: undefined, + }; + + await addOneEServiceTemplate(eserviceTemplate); + + await expect( + eserviceTemplateService.publishEServiceTemplateVersion( + eserviceTemplate.id, + eserviceTemplateVersion.id, + getMockContext({ + authData: getMockAuthData(eserviceTemplate.creatorId), + }) + ) + ).rejects.toThrowError( + eserviceTemplatePersonalDataMustBeSet( + eserviceTemplate.id, + eserviceTemplateVersion.id + ) + ); + }); }); From 03e20fce8b453abff078eee0af9165593a767456 Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Tue, 23 Sep 2025 15:06:40 +0200 Subject: [PATCH 073/180] feat(eservice-template-outbound-writer): add event EServiceTemplatePersonalDataUpdatedAfterPublish --- .../src/converters/toOutboundEventV2.ts | 1 + .../models/proto/v2/eservice-template/events.proto | 4 ++++ .../src/eservice-template/eserviceTemplateEvents.ts | 11 +++++++++++ 3 files changed, 16 insertions(+) diff --git a/packages/eservice-template-outbound-writer/src/converters/toOutboundEventV2.ts b/packages/eservice-template-outbound-writer/src/converters/toOutboundEventV2.ts index c69315b3c9..3cb745043c 100644 --- a/packages/eservice-template-outbound-writer/src/converters/toOutboundEventV2.ts +++ b/packages/eservice-template-outbound-writer/src/converters/toOutboundEventV2.ts @@ -55,6 +55,7 @@ export function toOutboundEventV2( { type: "EServiceTemplateDeleted" }, { type: "EServiceTemplateIntendedTargetUpdated" }, { type: "EServiceTemplateDescriptionUpdated" }, + { type: "EServiceTemplatePersonalDataUpdatedAfterPublish" }, (msg) => ({ event_version: msg.event_version, type: msg.type, diff --git a/packages/models/proto/v2/eservice-template/events.proto b/packages/models/proto/v2/eservice-template/events.proto index 71142fdfb8..ea4730d469 100644 --- a/packages/models/proto/v2/eservice-template/events.proto +++ b/packages/models/proto/v2/eservice-template/events.proto @@ -120,3 +120,7 @@ message EServiceTemplateVersionActivatedV2 { string eserviceTemplateVersionId = 1; EServiceTemplateV2 eserviceTemplate = 2; } + +message EServiceTemplatePersonalDataUpdatedAfterPublishV2 { + EServiceTemplateV2 eserviceTemplate = 1; +} diff --git a/packages/models/src/eservice-template/eserviceTemplateEvents.ts b/packages/models/src/eservice-template/eserviceTemplateEvents.ts index f1b1c2ff62..85cf6ea3d3 100644 --- a/packages/models/src/eservice-template/eserviceTemplateEvents.ts +++ b/packages/models/src/eservice-template/eserviceTemplateEvents.ts @@ -25,6 +25,7 @@ import { EServiceTemplateVersionInterfaceUpdatedV2, EServiceTemplateVersionPublishedV2, EServiceTemplateVersionQuotasUpdatedV2, + EServiceTemplatePersonalDataUpdatedAfterPublishV2, } from "../gen/v2/eservice-template/events.js"; import { protobufDecoder } from "../protobuf/protobuf.js"; import { EventEnvelope } from "../events/events.js"; @@ -145,6 +146,11 @@ export const EServiceTemplateEventV2 = z.discriminatedUnion("type", [ type: z.literal("EServiceTemplateVersionActivated"), data: protobufDecoder(EServiceTemplateVersionActivatedV2), }), + z.object({ + event_version: z.literal(2), + type: z.literal("EServiceTemplatePersonalDataUpdatedAfterPublish"), + data: protobufDecoder(EServiceTemplatePersonalDataUpdatedAfterPublishV2), + }), ]); export type EServiceTemplateEventV2 = z.infer; @@ -222,6 +228,11 @@ export function eserviceTemplateEventToBinaryDataV2( .with({ type: "EServiceTemplateVersionQuotasUpdated" }, ({ data }) => EServiceTemplateVersionQuotasUpdatedV2.toBinary(data) ) + .with( + { type: "EServiceTemplatePersonalDataUpdatedAfterPublish" }, + ({ data }) => + EServiceTemplatePersonalDataUpdatedAfterPublishV2.toBinary(data) + ) .exhaustive(); } From b8c1f7b04b004651aab7b9391c3bd462cde7795b Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Tue, 23 Sep 2025 16:51:13 +0200 Subject: [PATCH 074/180] Remove todo --- .../catalog-outbound-writer/src/converters/toOutboundEventV2.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/catalog-outbound-writer/src/converters/toOutboundEventV2.ts b/packages/catalog-outbound-writer/src/converters/toOutboundEventV2.ts index af0b1ec78f..d93b4df79f 100644 --- a/packages/catalog-outbound-writer/src/converters/toOutboundEventV2.ts +++ b/packages/catalog-outbound-writer/src/converters/toOutboundEventV2.ts @@ -97,6 +97,7 @@ export function toOutboundEventV2( { type: "EServiceNameUpdatedByTemplateUpdate" }, { type: "EServiceSignalHubEnabled" }, { type: "EServiceSignalHubDisabled" }, + { type: "EServicePersonalDataUpdatedAfterPublish" }, (msg) => ({ event_version: msg.event_version, type: msg.type, @@ -212,7 +213,6 @@ export function toOutboundEventV2( { type: "EServiceRiskAnalysisAdded" }, { type: "EServiceRiskAnalysisDeleted" }, { type: "EServiceRiskAnalysisUpdated" }, - { type: "EServicePersonalDataUpdatedAfterPublish" }, // TODO move to the first handler after outbound gets updated () => undefined ) .exhaustive(); From e74b43fb9dd6e4cd0785a2f9ab47eaa84b267bd6 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Tue, 23 Sep 2025 18:06:37 +0200 Subject: [PATCH 075/180] Fix test --- packages/readmodel/test/eserviceTemplateSplitter.test.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/readmodel/test/eserviceTemplateSplitter.test.ts b/packages/readmodel/test/eserviceTemplateSplitter.test.ts index d0653688f7..1921ebf4fa 100644 --- a/packages/readmodel/test/eserviceTemplateSplitter.test.ts +++ b/packages/readmodel/test/eserviceTemplateSplitter.test.ts @@ -40,6 +40,7 @@ describe("E-service template splitter", () => { const suspendedAt = new Date(); const deprecatedAt = new Date(); const isSignalHubEnabled = true; + const personalData = true; const version: EServiceTemplateVersion = { ...getMockEServiceTemplateVersion(), @@ -87,6 +88,7 @@ describe("E-service template splitter", () => { technology: eserviceTemplate.technology, mode: eserviceTemplate.mode, isSignalHubEnabled, + personalData, }; const expectedRiskAnalysisSQL1: EServiceTemplateRiskAnalysisSQL = { @@ -235,6 +237,7 @@ describe("E-service template splitter", () => { technology: eserviceTemplate.technology, mode: eserviceTemplate.mode, isSignalHubEnabled: null, + personalData: null, }; const expectedRiskAnalysisSQL1: EServiceTemplateRiskAnalysisSQL = { From a20e65a0774af187c8f475dc94f4d769a831351e Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Tue, 23 Sep 2025 22:44:02 +0200 Subject: [PATCH 076/180] feat(eservice-template-readmodel-writer-sql): add personalData event in consumerServiceV2 --- .../src/consumerServiceV2.ts | 1 + .../test/eserviceTemplateQueries.test.ts | 2 + ...emplateReadmodelWriter.integration.test.ts | 43 +++++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/packages/eservice-template-readmodel-writer-sql/src/consumerServiceV2.ts b/packages/eservice-template-readmodel-writer-sql/src/consumerServiceV2.ts index 39579021c4..467abaff60 100644 --- a/packages/eservice-template-readmodel-writer-sql/src/consumerServiceV2.ts +++ b/packages/eservice-template-readmodel-writer-sql/src/consumerServiceV2.ts @@ -49,6 +49,7 @@ export async function handleMessageV2( { type: "EServiceTemplateVersionInterfaceUpdated" }, { type: "EServiceTemplateVersionPublished" }, { type: "EServiceTemplateVersionQuotasUpdated" }, + { type: "EServiceTemplatePersonalDataUpdatedAfterPublish" }, async (message) => { await eserviceTemplateWriterService.upsertEServiceTemplate( fromEServiceTemplateV2(eserviceTemplate), diff --git a/packages/eservice-template-readmodel-writer-sql/test/eserviceTemplateQueries.test.ts b/packages/eservice-template-readmodel-writer-sql/test/eserviceTemplateQueries.test.ts index 45a626496d..9be55cf7a3 100644 --- a/packages/eservice-template-readmodel-writer-sql/test/eserviceTemplateQueries.test.ts +++ b/packages/eservice-template-readmodel-writer-sql/test/eserviceTemplateQueries.test.ts @@ -60,6 +60,7 @@ describe("E-service template queries", () => { getMockValidEServiceTemplateRiskAnalysis(tenantKind.PRIVATE), ], isSignalHubEnabled: true, + personalData: false, }; await eserviceTemplateWriterService.upsertEServiceTemplate( @@ -195,6 +196,7 @@ describe("E-service template queries", () => { getMockValidEServiceTemplateRiskAnalysis(tenantKind.PRIVATE), ], isSignalHubEnabled: true, + personalData: false, }; await eserviceTemplateWriterService.upsertEServiceTemplate( diff --git a/packages/eservice-template-readmodel-writer-sql/test/eserviceTemplateReadmodelWriter.integration.test.ts b/packages/eservice-template-readmodel-writer-sql/test/eserviceTemplateReadmodelWriter.integration.test.ts index c96bd56178..a5195bf193 100644 --- a/packages/eservice-template-readmodel-writer-sql/test/eserviceTemplateReadmodelWriter.integration.test.ts +++ b/packages/eservice-template-readmodel-writer-sql/test/eserviceTemplateReadmodelWriter.integration.test.ts @@ -933,5 +933,48 @@ describe("database test", async () => { expect(retrievedEservice?.data).toStrictEqual(updatedEServiceTemplate); expect(retrievedEservice?.metadata).toStrictEqual({ version: 2 }); }); + + it("EServiceTemplatePersonalDataUpdatedAfterPublish", async () => { + const publishedVersion: EServiceTemplateVersion = { + ...getMockEServiceTemplateVersion(), + interface: getMockDocument(), + state: eserviceTemplateVersionState.published, + publishedAt: new Date(), + }; + const eserviceTemplate: EServiceTemplate = { + ...mockEServiceTemplate, + versions: [publishedVersion], + }; + await eserviceTemplateWriterService.upsertEServiceTemplate( + eserviceTemplate, + 1 + ); + const updatedEServiceTemplate: EServiceTemplate = { + ...eserviceTemplate, + personalData: false, + }; + const payload = { + eserviceTemplate: toEServiceTemplateV2(updatedEServiceTemplate), + }; + const message: EServiceTemplateEventEnvelope = { + sequence_num: 1, + stream_id: mockEServiceTemplate.id, + version: 2, + type: "EServiceTemplatePersonalDataUpdatedAfterPublish", + event_version: 2, + data: payload, + log_date: new Date(), + }; + + await handleMessageV2(message, eserviceTemplateWriterService); + + const retrievedEservice = + await eserviceTemplateReadModelService.getEServiceTemplateById( + mockEServiceTemplate.id + ); + + expect(retrievedEservice?.data).toStrictEqual(updatedEServiceTemplate); + expect(retrievedEservice?.metadata).toStrictEqual({ version: 2 }); + }); }); }); From 43ed29589b7173e67aa79c0809668fcd5af46f41 Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Tue, 23 Sep 2025 22:44:42 +0200 Subject: [PATCH 077/180] feat(eservice-template-process): implement personalData endpoint + tests --- .../open-api/eserviceTemplateApi.yml | 64 +++++++ .../src/model/domain/apiConverter.ts | 1 + .../src/model/domain/errors.ts | 11 ++ .../src/model/domain/toEvent.ts | 17 ++ .../src/routers/EServiceTemplateRouter.ts | 35 ++++ .../src/services/eserviceTemplateService.ts | 43 +++++ .../src/utilities/errorMappers.ts | 13 ++ ...updateEServiceTemplatePersonalData.test.ts | 137 ++++++++++++++ ...atePersonalDataUpdatedAfterPublish.test.ts | 173 ++++++++++++++++++ 9 files changed, 494 insertions(+) create mode 100644 packages/eservice-template-process/test/api/updateEServiceTemplatePersonalData.test.ts create mode 100644 packages/eservice-template-process/test/integration/updateEServiceTemplatePersonalDataUpdatedAfterPublish.test.ts diff --git a/packages/api-clients/open-api/eserviceTemplateApi.yml b/packages/api-clients/open-api/eserviceTemplateApi.yml index 0f8d1906ae..91d25685b7 100644 --- a/packages/api-clients/open-api/eserviceTemplateApi.yml +++ b/packages/api-clients/open-api/eserviceTemplateApi.yml @@ -1170,6 +1170,62 @@ paths: application/problem+json: schema: $ref: "#/components/schemas/Problem" + /templates/{templateId}/personalData: + parameters: + - $ref: "#/components/parameters/CorrelationIdHeader" + post: + security: + - bearerAuth: [] + tags: + - process + summary: Set personalData flag for published e-service templates + operationId: updateEServiceTemplatePersonalDataAfterPublish + parameters: + - name: templateId + in: path + description: the eservice template id + required: true + schema: + type: string + format: uuid + requestBody: + description: EService template personalData flag updated + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/EServiceTemplatePersonalDataUpdateSeed" + responses: + "200": + description: EService template personalData flag updated + content: + application/json: + schema: + $ref: "#/components/schemas/EServiceTemplate" + "400": + description: Bad request + content: + application/json: + schema: + $ref: "#/components/schemas/Problem" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: "#/components/schemas/Problem" + "404": + description: EService template not found + content: + application/json: + schema: + $ref: "#/components/schemas/Problem" + "409": + description: Conflict + content: + application/json: + schema: + $ref: "#/components/schemas/Problem" "/creators": parameters: - $ref: "#/components/parameters/CorrelationIdHeader" @@ -1424,6 +1480,14 @@ components: type: string minLength: 5 maxLength: 60 + EServiceTemplatePersonalDataUpdateSeed: + type: object + additionalProperties: false + properties: + personalData: + type: boolean + required: + - personalData AttributesSeed: additionalProperties: false properties: diff --git a/packages/eservice-template-process/src/model/domain/apiConverter.ts b/packages/eservice-template-process/src/model/domain/apiConverter.ts index c9fc76741f..d923f85026 100644 --- a/packages/eservice-template-process/src/model/domain/apiConverter.ts +++ b/packages/eservice-template-process/src/model/domain/apiConverter.ts @@ -170,4 +170,5 @@ export const eserviceTemplateToApiEServiceTemplate = ( eserviceTemplateVersionToApiEServiceTemplateVersion ), isSignalHubEnabled: eserviceTemplate.isSignalHubEnabled, + personalData: eserviceTemplate.personalData, }); diff --git a/packages/eservice-template-process/src/model/domain/errors.ts b/packages/eservice-template-process/src/model/domain/errors.ts index c7c65c747f..c2a597d516 100644 --- a/packages/eservice-template-process/src/model/domain/errors.ts +++ b/packages/eservice-template-process/src/model/domain/errors.ts @@ -35,6 +35,7 @@ export const errorCodes = { riskAnalysisNotFound: "0026", attributeDuplicatedInGroup: "0027", eserviceTemplatePersonalDataMustBeSet: "0028", + eserviceTemplatePersonalDataCanOnlyBeSetOnce: "0029", }; export type ErrorCodes = keyof typeof errorCodes; @@ -310,3 +311,13 @@ export function eserviceTemplatePersonalDataMustBeSet( title: "EService Template personalData must be set before publication", }); } + +export function eserviceTemplatePersonalDataCanOnlyBeSetOnce( + eserviceTemplateId: EServiceTemplateId +): ApiError { + return new ApiError({ + detail: `PersonalData flag has already been set for eService Template ${eserviceTemplateId}`, + code: "eserviceTemplatePersonalDataCanOnlyBeSetOnce", + title: "EService Template personalData can only be set once", + }); +} diff --git a/packages/eservice-template-process/src/model/domain/toEvent.ts b/packages/eservice-template-process/src/model/domain/toEvent.ts index 3a4626aac4..32b766eb99 100644 --- a/packages/eservice-template-process/src/model/domain/toEvent.ts +++ b/packages/eservice-template-process/src/model/domain/toEvent.ts @@ -470,3 +470,20 @@ export const toCreateEventEServiceTemplateVersionActivated = ( }, correlationId, }); + +export const toCreateEventEServiceTemplatePersonalDataUpdatedAfterPublish = ( + version: number, + eserviceTemplate: EServiceTemplate, + correlationId: CorrelationId +): CreateEvent => ({ + streamId: eserviceTemplate.id, + version, + event: { + type: "EServiceTemplatePersonalDataUpdatedAfterPublish", + event_version: 2, + data: { + eserviceTemplate: toEServiceTemplateV2(eserviceTemplate), + }, + }, + correlationId, +}); diff --git a/packages/eservice-template-process/src/routers/EServiceTemplateRouter.ts b/packages/eservice-template-process/src/routers/EServiceTemplateRouter.ts index ef9ea7f998..3b9cf9ffdf 100644 --- a/packages/eservice-template-process/src/routers/EServiceTemplateRouter.ts +++ b/packages/eservice-template-process/src/routers/EServiceTemplateRouter.ts @@ -40,6 +40,7 @@ import { updateDocumentErrorMapper, deleteDocumentErrorMapper, getEServiceTemplatesErrorMapper, + updateEServiceTemplatePersonalDataErrorMapper, } from "../utilities/errorMappers.js"; import { eserviceTemplateToApiEServiceTemplate, @@ -47,6 +48,7 @@ import { apiEServiceTemplateVersionStateToEServiceTemplateVersionState, documentToApiDocument, } from "../model/domain/apiConverter.js"; +import { config } from "../config/config.js"; const eserviceTemplatesRouter = ( ctx: ZodiosContext, @@ -696,6 +698,39 @@ const eserviceTemplatesRouter = ( } } ) + .post("/templates/:templateId/personalData", async (req, res) => { + const ctx = fromAppContext(req.ctx); + + try { + validateAuthorization(ctx, [ADMIN_ROLE, API_ROLE]); + + if (config.featureFlagEservicePersonalData === false) { + return res.status(501).send(); + } + + const updatedEServiceTemplate = + await eserviceTemplateService.updateEServiceTemplatePersonalDataAfterPublish( + unsafeBrandId(req.params.templateId), + req.body.personalData, + ctx + ); + + return res + .status(200) + .send( + eserviceTemplateApi.EServiceTemplate.parse( + eserviceTemplateToApiEServiceTemplate(updatedEServiceTemplate) + ) + ); + } catch (error) { + const errorRes = makeApiProblem( + error, + updateEServiceTemplatePersonalDataErrorMapper, + ctx + ); + return res.status(errorRes.status).send(errorRes); + } + }) .get("/creators", async (req, res) => { const ctx = fromAppContext(req.ctx); diff --git a/packages/eservice-template-process/src/services/eserviceTemplateService.ts b/packages/eservice-template-process/src/services/eserviceTemplateService.ts index c0132436f7..743897ace3 100644 --- a/packages/eservice-template-process/src/services/eserviceTemplateService.ts +++ b/packages/eservice-template-process/src/services/eserviceTemplateService.ts @@ -50,6 +50,7 @@ import { notValidEServiceTemplateVersionState, attributeDuplicatedInGroup, eserviceTemplatePersonalDataMustBeSet, + eserviceTemplatePersonalDataCanOnlyBeSetOnce, } from "../model/domain/errors.js"; import { versionAttributeGroupSupersetMissingInAttributesSeed, @@ -87,6 +88,7 @@ import { toCreateEventEServiceTemplateVersionDocumentUpdated, toCreateEventEServiceTemplateVersionDocumentDeleted, toCreateEventEServiceTemplateVersionInterfaceDeleted, + toCreateEventEServiceTemplatePersonalDataUpdatedAfterPublish, } from "../model/domain/toEvent.js"; import { config } from "../config/config.js"; import { @@ -1792,6 +1794,47 @@ export function eserviceTemplateServiceBuilder( await repository.createEvent(event); }, + async updateEServiceTemplatePersonalDataAfterPublish( + eserviceTemplateId: EServiceTemplateId, + personalData: boolean, + { authData, correlationId, logger }: WithLogger> + ): Promise { + logger.info( + `Setting personalData flag for EServiceTemplate ${eserviceTemplateId} to ${personalData}` + ); + + const eserviceTemplate = await retrieveEServiceTemplate( + eserviceTemplateId, + readModelService + ); + + assertRequesterEServiceTemplateCreator( + eserviceTemplate.data.creatorId, + authData + ); + + assertPublishedEServiceTemplate(eserviceTemplate.data); + + if (eserviceTemplate.data.personalData !== undefined) { + throw eserviceTemplatePersonalDataCanOnlyBeSetOnce(eserviceTemplateId); + } + + const updatedEServiceTemplate: EServiceTemplate = { + ...eserviceTemplate.data, + personalData, + }; + + const event = + toCreateEventEServiceTemplatePersonalDataUpdatedAfterPublish( + eserviceTemplate.metadata.version, + updatedEServiceTemplate, + correlationId + ); + + await repository.createEvent(event); + + return updatedEServiceTemplate; + }, }; } diff --git a/packages/eservice-template-process/src/utilities/errorMappers.ts b/packages/eservice-template-process/src/utilities/errorMappers.ts index 744ba2fb4e..6fb6b8e833 100644 --- a/packages/eservice-template-process/src/utilities/errorMappers.ts +++ b/packages/eservice-template-process/src/utilities/errorMappers.ts @@ -311,3 +311,16 @@ export const getEServiceTemplatesErrorMapper = ( match(error.code) .with("eserviceTemplateNotFound", () => HTTP_STATUS_NOT_FOUND) .otherwise(() => HTTP_STATUS_INTERNAL_SERVER_ERROR); + +export const updateEServiceTemplatePersonalDataErrorMapper = ( + error: ApiError +): number => + match(error.code) + .with("eserviceTemplateNotFound", () => HTTP_STATUS_NOT_FOUND) + .with("operationForbidden", () => HTTP_STATUS_FORBIDDEN) + .with( + "eserviceTemplateWithoutPublishedVersion", + "eserviceTemplatePersonalDataCanOnlyBeSetOnce", + () => HTTP_STATUS_CONFLICT + ) + .otherwise(() => HTTP_STATUS_INTERNAL_SERVER_ERROR); diff --git a/packages/eservice-template-process/test/api/updateEServiceTemplatePersonalData.test.ts b/packages/eservice-template-process/test/api/updateEServiceTemplatePersonalData.test.ts new file mode 100644 index 0000000000..be3f9e8768 --- /dev/null +++ b/packages/eservice-template-process/test/api/updateEServiceTemplatePersonalData.test.ts @@ -0,0 +1,137 @@ +/* eslint-disable @typescript-eslint/explicit-function-return-type */ +import { describe, it, expect, vi } from "vitest"; +import request from "supertest"; +import { + EServiceTemplate, + EServiceTemplateId, + EServiceTemplateVersion, + eserviceTemplateVersionState, + operationForbidden, + generateId, +} from "pagopa-interop-models"; +import { + generateToken, + randomArrayItem, + getMockEServiceTemplate, + getMockEServiceTemplateVersion, + getMockDocument, +} from "pagopa-interop-commons-test"; +import { AuthRole, authRole } from "pagopa-interop-commons"; +import { eserviceTemplateApi } from "pagopa-interop-api-clients"; +import { api, eserviceTemplateService } from "../vitest.api.setup.js"; +import { eserviceTemplateToApiEServiceTemplate } from "../../src/model/domain/apiConverter.js"; +import { + eserviceTemplateNotFound, + eserviceTemplateWithoutPublishedVersion, + eserviceTemplatePersonalDataCanOnlyBeSetOnce, +} from "../../src/model/domain/errors.js"; + +describe("API /templates/{templateId}/personalData", () => { + const eserviceTemplateVersion: EServiceTemplateVersion = { + ...getMockEServiceTemplateVersion(), + state: eserviceTemplateVersionState.published, + interface: getMockDocument(), + }; + + const mockEServiceTemplate: EServiceTemplate = { + ...getMockEServiceTemplate(), + versions: [eserviceTemplateVersion], + }; + + const serviceResponse = mockEServiceTemplate; + const apiEserviceTemplate = eserviceTemplateApi.EServiceTemplate.parse( + eserviceTemplateToApiEServiceTemplate(mockEServiceTemplate) + ); + + const personalData = randomArrayItem([false, true]); + + const eserviceTemplateSeed: eserviceTemplateApi.EServiceTemplatePersonalDataUpdateSeed = + { personalData }; + + eserviceTemplateService.updateEServiceTemplatePersonalDataAfterPublish = vi + .fn() + .mockResolvedValue(serviceResponse); + + const makeRequest = async ( + token: string, + templateId: EServiceTemplateId, + body: eserviceTemplateApi.EServiceTemplatePersonalDataUpdateSeed = eserviceTemplateSeed + ) => + request(api) + .post(`/templates/${templateId}/personalData`) + .set("Authorization", `Bearer ${token}`) + .set("X-Correlation-Id", generateId()) + .send(body); + + const authorizedRoles: AuthRole[] = [authRole.ADMIN_ROLE, authRole.API_ROLE]; + + it.each(authorizedRoles)( + "Should return 200 for user with role %s", + async (role) => { + const token = generateToken(role); + const res = await makeRequest(token, mockEServiceTemplate.id); + + expect(res.status).toBe(200); + expect(res.body).toEqual(apiEserviceTemplate); + } + ); + + it.each( + Object.values(authRole).filter((role) => !authorizedRoles.includes(role)) + )("Should return 403 for user with role %s", async (role) => { + const token = generateToken(role); + const res = await makeRequest(token, mockEServiceTemplate.id); + + expect(res.status).toBe(403); + }); + + it.each([ + { + error: eserviceTemplateWithoutPublishedVersion(mockEServiceTemplate.id), + expectedStatus: 409, + }, + { + error: eserviceTemplatePersonalDataCanOnlyBeSetOnce( + mockEServiceTemplate.id + ), + expectedStatus: 409, + }, + { + error: eserviceTemplateNotFound(mockEServiceTemplate.id), + expectedStatus: 404, + }, + { + error: operationForbidden, + expectedStatus: 403, + }, + ])( + "Should return $expectedStatus for $error.code", + async ({ error, expectedStatus }) => { + eserviceTemplateService.updateEServiceTemplatePersonalDataAfterPublish = + vi.fn().mockRejectedValue(error); + + const token = generateToken(authRole.ADMIN_ROLE); + const res = await makeRequest(token, mockEServiceTemplate.id); + + expect(res.status).toBe(expectedStatus); + } + ); + + it.each([ + [{}, mockEServiceTemplate.id], + [{ personalData: "notABool" }, mockEServiceTemplate.id], + [{ ...eserviceTemplateSeed }, "invalidId"], + ])( + "Should return 400 if passed invalid personalData update params: %s (templateId: %s)", + async (body, templateId) => { + const token = generateToken(authRole.ADMIN_ROLE); + const res = await makeRequest( + token, + templateId as EServiceTemplateId, + body as eserviceTemplateApi.EServiceTemplatePersonalDataUpdateSeed + ); + + expect(res.status).toBe(400); + } + ); +}); diff --git a/packages/eservice-template-process/test/integration/updateEServiceTemplatePersonalDataUpdatedAfterPublish.test.ts b/packages/eservice-template-process/test/integration/updateEServiceTemplatePersonalDataUpdatedAfterPublish.test.ts new file mode 100644 index 0000000000..df7889cf6b --- /dev/null +++ b/packages/eservice-template-process/test/integration/updateEServiceTemplatePersonalDataUpdatedAfterPublish.test.ts @@ -0,0 +1,173 @@ +/* eslint-disable @typescript-eslint/no-floating-promises */ +import { + decodeProtobufPayload, + getMockContext, + getMockAuthData, + getMockEServiceTemplate, + getMockEServiceTemplateVersion, + getMockDocument, +} from "pagopa-interop-commons-test"; +import { + EServiceTemplate, + toEServiceTemplateV2, + EServiceTemplatePersonalDataUpdatedAfterPublishV2, + operationForbidden, + eserviceTemplateVersionState, + EServiceTemplateVersion, +} from "pagopa-interop-models"; +import { expect, describe, it } from "vitest"; +import { + addOneEServiceTemplate, + eserviceTemplateService, + readLastEserviceTemplateEvent, +} from "../integrationUtils.js"; +import { + eserviceTemplateNotFound, + eserviceTemplatePersonalDataCanOnlyBeSetOnce, + eserviceTemplateWithoutPublishedVersion, +} from "../../src/model/domain/errors.js"; + +describe("update EService Template personalData flag for an already created EService Template", async () => { + it("should write on event-store for the update of the EService Template personalData flag (undefined -> true)", async () => { + const eserviceTemplateVersion: EServiceTemplateVersion = { + ...getMockEServiceTemplateVersion(), + state: eserviceTemplateVersionState.published, + interface: getMockDocument(), + }; + + const eserviceTemplate: EServiceTemplate = { + ...getMockEServiceTemplate(), + versions: [eserviceTemplateVersion], + }; + + await addOneEServiceTemplate(eserviceTemplate); + const newPersonalDataValue = true; + + const returnedEServiceTemplate = + await eserviceTemplateService.updateEServiceTemplatePersonalDataAfterPublish( + eserviceTemplate.id, + newPersonalDataValue, + getMockContext({ + authData: getMockAuthData(eserviceTemplate.creatorId), + }) + ); + + const updatedEServiceTemplate: EServiceTemplate = { + ...eserviceTemplate, + personalData: newPersonalDataValue, + }; + + const writtenEvent = await readLastEserviceTemplateEvent( + eserviceTemplate.id + ); + expect(writtenEvent).toMatchObject({ + stream_id: eserviceTemplate.id, + version: "1", + type: "EServiceTemplatePersonalDataUpdatedAfterPublish", + event_version: 2, + }); + + const writtenPayload = decodeProtobufPayload({ + messageType: EServiceTemplatePersonalDataUpdatedAfterPublishV2, + payload: writtenEvent.data, + }); + + expect(writtenPayload.eserviceTemplate).toEqual( + toEServiceTemplateV2(updatedEServiceTemplate) + ); + expect(writtenPayload.eserviceTemplate).toEqual( + toEServiceTemplateV2(returnedEServiceTemplate) + ); + }); + + it.each([ + [true, true], + [false, false], + ])( + "should NOT write on event-store for the update if personalData was already set (%s -> %s)", + async (oldValue, newValue) => { + const eserviceTemplateVersion: EServiceTemplateVersion = { + ...getMockEServiceTemplateVersion(), + state: eserviceTemplateVersionState.published, + interface: getMockDocument(), + }; + + const eserviceTemplate: EServiceTemplate = { + ...getMockEServiceTemplate(), + versions: [eserviceTemplateVersion], + personalData: oldValue, + }; + + await addOneEServiceTemplate(eserviceTemplate); + + await expect( + eserviceTemplateService.updateEServiceTemplatePersonalDataAfterPublish( + eserviceTemplate.id, + newValue, + getMockContext({ + authData: getMockAuthData(eserviceTemplate.creatorId), + }) + ) + ).rejects.toThrowError( + eserviceTemplatePersonalDataCanOnlyBeSetOnce(eserviceTemplate.id) + ); + } + ); + + it.each([true, false])( + "should throw eserviceTemplateNotFound if the template doesn't exist (flag=%s)", + async (personalDataFlag) => { + const eserviceTemplate = getMockEServiceTemplate(); + + await expect( + eserviceTemplateService.updateEServiceTemplatePersonalDataAfterPublish( + eserviceTemplate.id, + personalDataFlag, + getMockContext({ + authData: getMockAuthData(eserviceTemplate.creatorId), + }) + ) + ).rejects.toThrowError(eserviceTemplateNotFound(eserviceTemplate.id)); + } + ); + + it.each([true, false])( + "should throw operationForbidden if the requester is not the creator (flag=%s)", + async (personalDataFlag) => { + const eserviceTemplate = getMockEServiceTemplate(); + await addOneEServiceTemplate(eserviceTemplate); + + await expect( + eserviceTemplateService.updateEServiceTemplatePersonalDataAfterPublish( + eserviceTemplate.id, + personalDataFlag, + getMockContext({}) + ) + ).rejects.toThrowError(operationForbidden); + } + ); + + it.each([true, false])( + "should throw eserviceTemplateWithoutPublishedVersion if the template has no published versions (flag=%s)", + async (personalDataFlag) => { + const eserviceTemplate: EServiceTemplate = { + ...getMockEServiceTemplate(), + versions: [], + }; + + await addOneEServiceTemplate(eserviceTemplate); + + await expect( + eserviceTemplateService.updateEServiceTemplatePersonalDataAfterPublish( + eserviceTemplate.id, + personalDataFlag, + getMockContext({ + authData: getMockAuthData(eserviceTemplate.creatorId), + }) + ) + ).rejects.toThrowError( + eserviceTemplateWithoutPublishedVersion(eserviceTemplate.id) + ); + } + ); +}); From b89a522269ed1aa5f23d13104d42e202500e28b8 Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Wed, 24 Sep 2025 00:33:43 +0200 Subject: [PATCH 078/180] feat(bff): add endpoint to update personalData flag for EServiceTemplates --- packages/api-clients/open-api/bffApi.yml | 138 ++++++++++++++++++ .../src/routers/eserviceTemplateRouter.ts | 22 +++ .../src/services/eserviceTemplateService.ts | 19 ++- ...updateEServiceTemplatePersonalData.test.ts | 86 +++++++++++ .../backend-for-frontend/test/mockUtils.ts | 5 + 5 files changed, 269 insertions(+), 1 deletion(-) create mode 100644 packages/backend-for-frontend/test/api/eserviceTemplateRouter/updateEServiceTemplatePersonalData.test.ts diff --git a/packages/api-clients/open-api/bffApi.yml b/packages/api-clients/open-api/bffApi.yml index 8a14a6a994..e8b7b13cd6 100644 --- a/packages/api-clients/open-api/bffApi.yml +++ b/packages/api-clients/open-api/bffApi.yml @@ -19968,6 +19968,136 @@ paths: application/problem+json: schema: $ref: "#/components/schemas/Problem" + /eservices/templates/{eServiceTemplateId}/personalData: + post: + security: + - bearerAuth: [] + tags: + - eserviceTemplates + summary: Set personalData flag for published EService templates + operationId: updateEServiceTemplatePersonalDataAfterPublish + parameters: + - name: eServiceTemplateId + in: path + description: the eservice template id + required: true + schema: + type: string + format: uuid + requestBody: + description: A payload containing a boolean that describes the personalData flag + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/EServiceTemplatePersonalDataUpdateSeed" + responses: + "204": + description: EService template personalData flag updated + headers: + "X-Rate-Limit-Limit": + schema: + type: integer + format: int32 + description: Max allowed requests within time interval + "X-Rate-Limit-Remaining": + schema: + type: integer + format: int32 + description: Remaining requests within time interval + "X-Rate-Limit-Interval": + schema: + type: integer + format: int32 + description: Time interval in milliseconds. Allowed requests will be constantly replenished during the interval. At the end of the interval the max allowed requests will be available + "400": + description: Bad request + content: + application/problem+json: + schema: + $ref: "#/components/schemas/Problem" + headers: + "X-Rate-Limit-Limit": + schema: + type: integer + format: int32 + description: Max allowed requests within time interval + "X-Rate-Limit-Remaining": + schema: + type: integer + format: int32 + description: Remaining requests within time interval + "X-Rate-Limit-Interval": + schema: + type: integer + format: int32 + description: Time interval in milliseconds. Allowed requests will be constantly replenished during the interval. At the end of the interval the max allowed requests will be available + "403": + description: Forbidden + content: + application/problem+json: + schema: + $ref: "#/components/schemas/Problem" + headers: + "X-Rate-Limit-Limit": + schema: + type: integer + format: int32 + description: Max allowed requests within time interval + "X-Rate-Limit-Remaining": + schema: + type: integer + format: int32 + description: Remaining requests within time interval + "X-Rate-Limit-Interval": + schema: + type: integer + format: int32 + description: Time interval in milliseconds. Allowed requests will be constantly replenished during the interval. At the end of the interval the max allowed requests will be available + "404": + description: EService template not found + content: + application/problem+json: + schema: + $ref: "#/components/schemas/Problem" + headers: + "X-Rate-Limit-Limit": + schema: + type: integer + format: int32 + description: Max allowed requests within time interval + "X-Rate-Limit-Remaining": + schema: + type: integer + format: int32 + description: Remaining requests within time interval + "X-Rate-Limit-Interval": + schema: + type: integer + format: int32 + description: Time interval in milliseconds. Allowed requests will be constantly replenished during the interval. At the end of the interval the max allowed requests will be available + "409": + description: Conflict + content: + application/problem+json: + schema: + $ref: "#/components/schemas/Problem" + headers: + "X-Rate-Limit-Limit": + schema: + type: integer + format: int32 + description: Max allowed requests within time interval + "X-Rate-Limit-Remaining": + schema: + type: integer + format: int32 + description: Remaining requests within time interval + "X-Rate-Limit-Interval": + schema: + type: integer + format: int32 + description: Time interval in milliseconds. Allowed requests will be constantly replenished during the interval. At the end of the interval the max allowed requests will be available /eservices/names/availability: get: security: @@ -25047,6 +25177,14 @@ components: required: - id - explicitAttributeVerification + EServiceTemplatePersonalDataUpdateSeed: + type: object + additionalProperties: false + properties: + personalData: + type: boolean + required: + - personalData UpdateEServiceTemplateVersionDocumentSeed: required: - prettyName diff --git a/packages/backend-for-frontend/src/routers/eserviceTemplateRouter.ts b/packages/backend-for-frontend/src/routers/eserviceTemplateRouter.ts index 6384d5d325..8392d28bc4 100644 --- a/packages/backend-for-frontend/src/routers/eserviceTemplateRouter.ts +++ b/packages/backend-for-frontend/src/routers/eserviceTemplateRouter.ts @@ -320,6 +320,28 @@ const eserviceTemplateRouter = ( } } ) + .post( + "/eservices/templates/:eServiceTemplateId/personalData", + async (req, res) => { + const ctx = fromBffAppContext(req.ctx, req.headers); + try { + await eserviceTemplateService.updateEServiceTemplatePersonalDataFlag( + ctx, + unsafeBrandId(req.params.eServiceTemplateId), + req.body + ); + return res.status(204).send(); + } catch (error) { + const errorRes = makeApiProblem( + error, + emptyErrorMapper, + ctx, + `Error setting personalData flag for eservice template ${req.params.eServiceTemplateId}` + ); + return res.status(errorRes.status).send(errorRes); + } + } + ) .get("/catalog/eservices/templates", async (req, res) => { const ctx = fromBffAppContext(req.ctx, req.headers); const { q, creatorsIds, offset, limit } = req.query; diff --git a/packages/backend-for-frontend/src/services/eserviceTemplateService.ts b/packages/backend-for-frontend/src/services/eserviceTemplateService.ts index 9fec8ef12a..38fe3c2bc8 100644 --- a/packages/backend-for-frontend/src/services/eserviceTemplateService.ts +++ b/packages/backend-for-frontend/src/services/eserviceTemplateService.ts @@ -630,7 +630,6 @@ export function eserviceTemplateServiceBuilder( return { contentType, document: Buffer.from(stream) }; }, - updateEServiceTemplateDocumentById: async ( templateId: EServiceTemplateId, templateVersionId: EServiceTemplateVersionId, @@ -656,6 +655,24 @@ export function eserviceTemplateServiceBuilder( return { id, name, contentType, prettyName, checksum }; }, + updateEServiceTemplatePersonalDataFlag: async ( + { logger, headers }: WithLogger, + templateId: EServiceTemplateId, + personalDataSeed: bffApi.EServiceTemplatePersonalDataUpdateSeed + ): Promise => { + logger.info( + `Set personal flag for E-Service Template with id = ${templateId} to ${personalDataSeed.personalData}` + ); + await eserviceTemplateClient.updateEServiceTemplatePersonalDataAfterPublish( + personalDataSeed, + { + headers, + params: { + templateId, + }, + } + ); + }, deleteEServiceTemplateDocumentById: async ( templateId: EServiceTemplateId, templateVersionId: EServiceTemplateVersionId, diff --git a/packages/backend-for-frontend/test/api/eserviceTemplateRouter/updateEServiceTemplatePersonalData.test.ts b/packages/backend-for-frontend/test/api/eserviceTemplateRouter/updateEServiceTemplatePersonalData.test.ts new file mode 100644 index 0000000000..e704d9f6f3 --- /dev/null +++ b/packages/backend-for-frontend/test/api/eserviceTemplateRouter/updateEServiceTemplatePersonalData.test.ts @@ -0,0 +1,86 @@ +/* eslint-disable @typescript-eslint/explicit-function-return-type */ +import { describe, it, expect, vi, beforeEach } from "vitest"; +import { + EServiceTemplate, + EServiceTemplateId, + EServiceTemplateVersion, + eserviceTemplateVersionState, + generateId, +} from "pagopa-interop-models"; +import { + generateToken, + getMockDocument, + getMockEServiceTemplate, + getMockEServiceTemplateVersion, +} from "pagopa-interop-commons-test"; +import { authRole } from "pagopa-interop-commons"; +import request from "supertest"; +import { bffApi } from "pagopa-interop-api-clients"; +import { api, clients } from "../../vitest.api.setup.js"; +import { appBasePath } from "../../../src/config/appBasePath.js"; +import { getMockBffApiEServiceTemplatePersonalDataUpdateSeed } from "../../mockUtils.js"; + +describe("API POST /eservices/templates/:eServiceTemplateId/personalData", () => { + const eserviceTemplateVersion: EServiceTemplateVersion = { + ...getMockEServiceTemplateVersion(), + state: eserviceTemplateVersionState.published, + interface: getMockDocument(), + }; + const mockEServiceTemplate: EServiceTemplate = { + ...getMockEServiceTemplate(), + versions: [eserviceTemplateVersion], + }; + const mockEServiceTemplatePersonalDataUpdateSeed = + getMockBffApiEServiceTemplatePersonalDataUpdateSeed(); + + beforeEach(() => { + clients.eserviceTemplateProcessClient.updateEServiceTemplatePersonalDataAfterPublish = + vi.fn().mockResolvedValue(mockEServiceTemplate); + }); + + const makeRequest = async ( + token: string, + eServiceTemplateId: EServiceTemplateId = mockEServiceTemplate.id, + body: bffApi.EServiceTemplatePersonalDataUpdateSeed = mockEServiceTemplatePersonalDataUpdateSeed + ) => + request(api) + .post( + `${appBasePath}/eservices/templates/${eServiceTemplateId}/personalData` + ) + .set("Authorization", `Bearer ${token}`) + .set("X-Correlation-Id", generateId()) + .send(body); + + it("Should return 204 for user with role Admin", async () => { + const token = generateToken(authRole.ADMIN_ROLE); + const res = await makeRequest(token); + expect(res.status).toBe(204); + }); + + it.each([ + { eServiceTemplateId: "invalid" as EServiceTemplateId }, + { body: {} }, + { + body: { + ...mockEServiceTemplatePersonalDataUpdateSeed, + extraField: 1, + }, + }, + { + body: { + personalData: "invalid", + }, + }, + ])( + "Should return 400 if passed invalid data: %s", + async ({ eServiceTemplateId, body }) => { + const token = generateToken(authRole.ADMIN_ROLE); + const res = await makeRequest( + token, + eServiceTemplateId, + body as bffApi.EServiceTemplatePersonalDataUpdateSeed + ); + expect(res.status).toBe(400); + } + ); +}); diff --git a/packages/backend-for-frontend/test/mockUtils.ts b/packages/backend-for-frontend/test/mockUtils.ts index f95c38f4c3..8f1edbdc27 100644 --- a/packages/backend-for-frontend/test/mockUtils.ts +++ b/packages/backend-for-frontend/test/mockUtils.ts @@ -452,6 +452,11 @@ export const getMockBffApiEServiceNameUpdateSeed = name: generateMock(z.string()), }); +export const getMockBffApiEServiceTemplatePersonalDataUpdateSeed = + (): bffApi.EServiceTemplatePersonalDataUpdateSeed => ({ + personalData: generateMock(z.boolean()), + }); + export const getMockBffApiUpdateEServiceTemplateInstanceSeed = // eslint-disable-next-line sonarjs/no-identical-functions (): bffApi.UpdateEServiceTemplateInstanceSeed => ({ From f3513801c766df89d97df828e9c88895c5e67dc5 Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Wed, 24 Sep 2025 00:34:49 +0200 Subject: [PATCH 079/180] feat: propagate EServiceTemplatePersonalDataUpdatedAfterPublish event to all consumers --- .../src/handlers/eservice-template/consumerServiceV2.ts | 3 ++- .../src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts | 1 + .../eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts | 1 + .../src/handlers/handleEServiceTemplateEvent.ts | 3 ++- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/domains-analytics-writer/src/handlers/eservice-template/consumerServiceV2.ts b/packages/domains-analytics-writer/src/handlers/eservice-template/consumerServiceV2.ts index 69bb33beaf..f65e736a9c 100644 --- a/packages/domains-analytics-writer/src/handlers/eservice-template/consumerServiceV2.ts +++ b/packages/domains-analytics-writer/src/handlers/eservice-template/consumerServiceV2.ts @@ -52,7 +52,8 @@ export async function handleEserviceTemplateMessageV2( "EServiceTemplateDraftVersionDeleted", "EServiceTemplateVersionInterfaceDeleted", "EServiceTemplateVersionDocumentDeleted", - "EServiceTemplateRiskAnalysisDeleted" + "EServiceTemplateRiskAnalysisDeleted", + "EServiceTemplatePersonalDataUpdatedAfterPublish" ), }, (msg) => { diff --git a/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts b/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts index 016b4e8d76..bad0d195f3 100644 --- a/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts +++ b/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts @@ -345,6 +345,7 @@ export async function handleMessageV2({ { type: "EServiceTemplateVersionInterfaceUpdated" }, { type: "EServiceTemplateVersionPublished" }, { type: "EServiceTemplateVersionSuspended" }, + { type: "EServiceTemplatePersonalDataUpdatedAfterPublish" }, () => Promise.resolve ) .exhaustive(); diff --git a/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts b/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts index 3d578a8b33..de717aca1b 100644 --- a/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts +++ b/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts @@ -919,6 +919,7 @@ describe("eserviceTemplateUpdaterConsumerServiceV2", () => { "EServiceTemplateVersionInterfaceUpdated", "EServiceTemplateVersionPublished", "EServiceTemplateVersionSuspended", + "EServiceTemplatePersonalDataUpdatedAfterPublish", ] as const)("Should ignore %s event", async (eventType) => { const decodedKafkaMessage: EServiceTemplateEventEnvelope = { sequence_num: 1, diff --git a/packages/m2m-event-dispatcher/src/handlers/handleEServiceTemplateEvent.ts b/packages/m2m-event-dispatcher/src/handlers/handleEServiceTemplateEvent.ts index 54f8707f7a..23878c4717 100644 --- a/packages/m2m-event-dispatcher/src/handlers/handleEServiceTemplateEvent.ts +++ b/packages/m2m-event-dispatcher/src/handlers/handleEServiceTemplateEvent.ts @@ -36,7 +36,8 @@ export async function handleEServiceTemplateEvent( "EServiceTemplateVersionInterfaceDeleted", "EServiceTemplateVersionInterfaceUpdated", "EServiceTemplateVersionPublished", - "EServiceTemplateVersionQuotasUpdated" + "EServiceTemplateVersionQuotasUpdated", + "EServiceTemplatePersonalDataUpdatedAfterPublish" ), }, () => Promise.resolve(void 0) From c3536d0fddd90f58c3d523c8f5cd1497d9c65b2a Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Wed, 24 Sep 2025 10:03:54 +0200 Subject: [PATCH 080/180] Fix test --- packages/readmodel/test/eserviceTemplateSplitter.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/readmodel/test/eserviceTemplateSplitter.test.ts b/packages/readmodel/test/eserviceTemplateSplitter.test.ts index 1921ebf4fa..e00cc2ac89 100644 --- a/packages/readmodel/test/eserviceTemplateSplitter.test.ts +++ b/packages/readmodel/test/eserviceTemplateSplitter.test.ts @@ -65,6 +65,7 @@ describe("E-service template splitter", () => { versions: [version], riskAnalysis: [riskAnalysisPA, riskAnalysisPrivate], isSignalHubEnabled, + personalData, }; const { From 583b76404e15b80729d8776c986eaf541ed1840d Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Wed, 24 Sep 2025 16:48:24 +0200 Subject: [PATCH 081/180] Fix merge --- .../src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts b/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts index 04f9e3d205..30ce5e793f 100644 --- a/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts +++ b/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts @@ -382,7 +382,6 @@ export async function handleMessageV2({ { type: "EServiceTemplateVersionInterfaceUpdated" }, { type: "EServiceTemplateVersionPublished" }, { type: "EServiceTemplateVersionSuspended" }, - { type: "EServiceTemplatePersonalDataUpdatedAfterPublish" }, () => Promise.resolve ) .exhaustive(); From d50ce094a4231c2d7e59a7cd751561d555e3fdc8 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Wed, 24 Sep 2025 17:52:59 +0200 Subject: [PATCH 082/180] Update test --- ...eInstancesUpdaterConsumerServiceV2.test.ts | 70 ++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts b/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts index de717aca1b..d3419f4fed 100644 --- a/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts +++ b/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts @@ -20,6 +20,7 @@ import { EServiceTemplateDescriptionUpdatedV2, EServiceTemplateEventEnvelope, EServiceTemplateNameUpdatedV2, + EServiceTemplatePersonalDataUpdatedAfterPublishV2, EServiceTemplateVersion, EServiceTemplateVersionAttributesUpdatedV2, EServiceTemplateVersionDocumentAddedV2, @@ -41,6 +42,7 @@ const updateTemplateInstanceDescriptorVoucherLifespanFn = vi.fn(); const createTemplateInstanceDescriptorDocumentFn = vi.fn(); const updateTemplateInstanceDescriptorDocumentFn = vi.fn(); const deleteTemplateInstanceDescriptorDocumentFn = vi.fn(); +const setTemplateInstancePersonalDataFn = vi.fn(); const copyDocumentFn = vi.fn(); @@ -64,6 +66,7 @@ vi.doMock("pagopa-interop-api-clients", () => ({ updateTemplateInstanceDescriptorDocumentFn, deleteTemplateInstanceDescriptorDocument: deleteTemplateInstanceDescriptorDocumentFn, + setTemplateInstancePersonalData: setTemplateInstancePersonalDataFn, }), }, })); @@ -902,6 +905,72 @@ describe("eserviceTemplateUpdaterConsumerServiceV2", () => { }); }); + it("The consumer should call the updateTemplateInstanceDPersonalFlag route on EServiceTemplatePersonalDataUpdatedAfterPublish event", async () => { + const payload: EServiceTemplatePersonalDataUpdatedAfterPublishV2 = { + eserviceTemplate: toEServiceTemplateV2({ + ...eserviceTemplate, + personalData: true, + }), + }; + + const decodedKafkaMessage: EServiceTemplateEventEnvelope = { + sequence_num: 1, + stream_id: eserviceTemplate.id, + version: 2, + type: "EServiceTemplatePersonalDataUpdatedAfterPublish", + event_version: 2, + data: payload, + log_date: new Date(), + correlation_id: correlationId, + }; + + await addOneEService(instanceToUpdate1); + await addOneEService(instanceToUpdate2); + await addOneEService(instanceToUpdate3); + + const { handleMessageV2 } = await import( + "../src/eserviceTemplateInstancesUpdaterConsumerServiceV2.js" + ); + + await handleMessageV2({ + decodedKafkaMessage, + refreshableToken: mockRefreshableToken, + partition: Math.random(), + offset: "10", + readModelService, + fileManager, + }); + + expect(setTemplateInstancePersonalDataFn).toHaveBeenCalledTimes(3); + expect(setTemplateInstancePersonalDataFn).toHaveBeenCalledWith( + { personalData: eserviceTemplate.personalData }, + { + params: { + eServiceId: instanceToUpdate1.id, + }, + headers: testHeaders, + } + ); + expect(setTemplateInstancePersonalDataFn).toHaveBeenCalledWith( + { personalData: eserviceTemplate.personalData }, + { + params: { + eServiceId: instanceToUpdate2.id, + }, + headers: testHeaders, + } + ); + expect(setTemplateInstancePersonalDataFn).toHaveBeenCalledWith( + { personalData: eserviceTemplate.personalData }, + { + params: { + eServiceId: instanceToUpdate3.id, + }, + headers: testHeaders, + } + ); + }); + it.each([ "EServiceTemplateAdded", "EServiceTemplateIntendedTargetUpdated", @@ -919,7 +988,6 @@ describe("eserviceTemplateUpdaterConsumerServiceV2", () => { "EServiceTemplateVersionInterfaceUpdated", "EServiceTemplateVersionPublished", "EServiceTemplateVersionSuspended", - "EServiceTemplatePersonalDataUpdatedAfterPublish", ] as const)("Should ignore %s event", async (eventType) => { const decodedKafkaMessage: EServiceTemplateEventEnvelope = { sequence_num: 1, From 70724b15493492dff795c9d6ff02dbb0060ce018 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Wed, 24 Sep 2025 18:03:47 +0200 Subject: [PATCH 083/180] Fix test --- ...plateInstancesUpdaterConsumerServiceV2.test.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts b/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts index d3419f4fed..c9dfce8f5f 100644 --- a/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts +++ b/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts @@ -906,11 +906,12 @@ describe("eserviceTemplateUpdaterConsumerServiceV2", () => { }); it("The consumer should call the updateTemplateInstanceDPersonalFlag route on EServiceTemplatePersonalDataUpdatedAfterPublish event", async () => { + const mockTemplate: EServiceTemplate = { + ...eserviceTemplate, + personalData: true, + }; const payload: EServiceTemplatePersonalDataUpdatedAfterPublishV2 = { - eserviceTemplate: toEServiceTemplateV2({ - ...eserviceTemplate, - personalData: true, - }), + eserviceTemplate: toEServiceTemplateV2(mockTemplate), }; const decodedKafkaMessage: EServiceTemplateEventEnvelope = { @@ -943,7 +944,7 @@ describe("eserviceTemplateUpdaterConsumerServiceV2", () => { expect(setTemplateInstancePersonalDataFn).toHaveBeenCalledTimes(3); expect(setTemplateInstancePersonalDataFn).toHaveBeenCalledWith( - { personalData: eserviceTemplate.personalData }, + { personalData: mockTemplate.personalData }, { params: { eServiceId: instanceToUpdate1.id, @@ -952,7 +953,7 @@ describe("eserviceTemplateUpdaterConsumerServiceV2", () => { } ); expect(setTemplateInstancePersonalDataFn).toHaveBeenCalledWith( - { personalData: eserviceTemplate.personalData }, + { personalData: mockTemplate.personalData }, { params: { eServiceId: instanceToUpdate2.id, @@ -961,7 +962,7 @@ describe("eserviceTemplateUpdaterConsumerServiceV2", () => { } ); expect(setTemplateInstancePersonalDataFn).toHaveBeenCalledWith( - { personalData: eserviceTemplate.personalData }, + { personalData: mockTemplate.personalData }, { params: { eServiceId: instanceToUpdate3.id, From 89c9d4b194e0bb12b52cc614b4cb7839dc91d21c Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Thu, 25 Sep 2025 09:38:13 +0200 Subject: [PATCH 084/180] test(eservice-template-instances-updater): fix misspelled test description --- .../eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts b/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts index c9dfce8f5f..76fd00b02c 100644 --- a/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts +++ b/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts @@ -905,7 +905,7 @@ describe("eserviceTemplateUpdaterConsumerServiceV2", () => { }); }); - it("The consumer should call the updateTemplateInstanceDPersonalFlag route on EServiceTemplatePersonalDataUpdatedAfterPublish event", async () => { + it("The consumer should call the updateTemplateInstanceDataPersonalFlag route on EServiceTemplatePersonalDataUpdatedAfterPublish event", async () => { const mockTemplate: EServiceTemplate = { ...eserviceTemplate, personalData: true, From ccbe34b4d0e8db809f2b47d7e7da18d11e9dd8a4 Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Thu, 25 Sep 2025 11:52:19 +0200 Subject: [PATCH 085/180] feat(catalog-process): add personalData to eServiceToApiEService and update OpenAPI spec --- packages/api-clients/open-api/catalogApi.yml | 3 +++ packages/catalog-process/src/model/domain/apiConverter.ts | 1 + 2 files changed, 4 insertions(+) diff --git a/packages/api-clients/open-api/catalogApi.yml b/packages/api-clients/open-api/catalogApi.yml index f8e8f4c139..9e1d128ee7 100644 --- a/packages/api-clients/open-api/catalogApi.yml +++ b/packages/api-clients/open-api/catalogApi.yml @@ -3136,6 +3136,9 @@ components: templateId: type: string format: uuid + personalData: + type: boolean + CreatedEServiceRiskAnalysis: type: object additionalProperties: false diff --git a/packages/catalog-process/src/model/domain/apiConverter.ts b/packages/catalog-process/src/model/domain/apiConverter.ts index aa5e7ae32e..c508792907 100644 --- a/packages/catalog-process/src/model/domain/apiConverter.ts +++ b/packages/catalog-process/src/model/domain/apiConverter.ts @@ -207,4 +207,5 @@ export const eServiceToApiEService = ( isConsumerDelegable: eservice.isConsumerDelegable, isClientAccessDelegable: eservice.isClientAccessDelegable, templateId: eservice.templateId, + personalData: eservice.personalData, }); From 85b531242470747f2f206e62aea482c8f3160bdb Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Thu, 25 Sep 2025 13:44:11 +0200 Subject: [PATCH 086/180] test(backend-for-frontend): fix API POST /eservices/templates/:eServiceTemplateId/personalData tests --- ...updateEServiceTemplatePersonalData.test.ts | 29 ++++--------------- 1 file changed, 5 insertions(+), 24 deletions(-) diff --git a/packages/backend-for-frontend/test/api/eserviceTemplateRouter/updateEServiceTemplatePersonalData.test.ts b/packages/backend-for-frontend/test/api/eserviceTemplateRouter/updateEServiceTemplatePersonalData.test.ts index e704d9f6f3..2422036a30 100644 --- a/packages/backend-for-frontend/test/api/eserviceTemplateRouter/updateEServiceTemplatePersonalData.test.ts +++ b/packages/backend-for-frontend/test/api/eserviceTemplateRouter/updateEServiceTemplatePersonalData.test.ts @@ -1,18 +1,7 @@ /* eslint-disable @typescript-eslint/explicit-function-return-type */ import { describe, it, expect, vi, beforeEach } from "vitest"; -import { - EServiceTemplate, - EServiceTemplateId, - EServiceTemplateVersion, - eserviceTemplateVersionState, - generateId, -} from "pagopa-interop-models"; -import { - generateToken, - getMockDocument, - getMockEServiceTemplate, - getMockEServiceTemplateVersion, -} from "pagopa-interop-commons-test"; +import { EServiceTemplateId, generateId } from "pagopa-interop-models"; +import { generateToken } from "pagopa-interop-commons-test"; import { authRole } from "pagopa-interop-commons"; import request from "supertest"; import { bffApi } from "pagopa-interop-api-clients"; @@ -21,26 +10,18 @@ import { appBasePath } from "../../../src/config/appBasePath.js"; import { getMockBffApiEServiceTemplatePersonalDataUpdateSeed } from "../../mockUtils.js"; describe("API POST /eservices/templates/:eServiceTemplateId/personalData", () => { - const eserviceTemplateVersion: EServiceTemplateVersion = { - ...getMockEServiceTemplateVersion(), - state: eserviceTemplateVersionState.published, - interface: getMockDocument(), - }; - const mockEServiceTemplate: EServiceTemplate = { - ...getMockEServiceTemplate(), - versions: [eserviceTemplateVersion], - }; + const mockEServiceTemplateId = generateId(); const mockEServiceTemplatePersonalDataUpdateSeed = getMockBffApiEServiceTemplatePersonalDataUpdateSeed(); beforeEach(() => { clients.eserviceTemplateProcessClient.updateEServiceTemplatePersonalDataAfterPublish = - vi.fn().mockResolvedValue(mockEServiceTemplate); + vi.fn().mockResolvedValue(undefined); }); const makeRequest = async ( token: string, - eServiceTemplateId: EServiceTemplateId = mockEServiceTemplate.id, + eServiceTemplateId: EServiceTemplateId = mockEServiceTemplateId, body: bffApi.EServiceTemplatePersonalDataUpdateSeed = mockEServiceTemplatePersonalDataUpdateSeed ) => request(api) From 59970598f51742ec8f4ea3272153a56df5d67262 Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Thu, 25 Sep 2025 14:00:50 +0200 Subject: [PATCH 087/180] test(backend-for-frontend): add personalData getMockCatalogApiEService --- packages/backend-for-frontend/test/mockUtils.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/backend-for-frontend/test/mockUtils.ts b/packages/backend-for-frontend/test/mockUtils.ts index f95c38f4c3..d96aec4a94 100644 --- a/packages/backend-for-frontend/test/mockUtils.ts +++ b/packages/backend-for-frontend/test/mockUtils.ts @@ -281,6 +281,7 @@ export const getMockCatalogApiEService = (): catalogApi.EService & { isConsumerDelegable: generateMock(z.boolean().optional()), isClientAccessDelegable: generateMock(z.boolean().optional()), templateId: generateMock(z.string().uuid().optional()), + personalData: generateMock(z.boolean().optional()), }); export const getMockBffApiFileResource = (): bffApi.FileResource => ({ From b28fac06c605ea4cc361f09671501e63b2c6a3cd Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Thu, 25 Sep 2025 14:37:40 +0200 Subject: [PATCH 088/180] test(backend-for-frontend): add getMockBffApiEServiceTemplatePersonalData and rename getMockBffApiEServiceTemplate --- .../createEServiceTemplate.test.ts | 4 +-- ...updateEServiceTemplatePersonalData.test.ts | 28 +++++++++++++++---- .../backend-for-frontend/test/mockUtils.ts | 14 ++++++++-- 3 files changed, 36 insertions(+), 10 deletions(-) diff --git a/packages/backend-for-frontend/test/api/eserviceTemplateRouter/createEServiceTemplate.test.ts b/packages/backend-for-frontend/test/api/eserviceTemplateRouter/createEServiceTemplate.test.ts index f1b01b5380..edc4d76bb9 100644 --- a/packages/backend-for-frontend/test/api/eserviceTemplateRouter/createEServiceTemplate.test.ts +++ b/packages/backend-for-frontend/test/api/eserviceTemplateRouter/createEServiceTemplate.test.ts @@ -8,7 +8,7 @@ import { bffApi } from "pagopa-interop-api-clients"; import { api, clients } from "../../vitest.api.setup.js"; import { appBasePath } from "../../../src/config/appBasePath.js"; import { - getMockBffApiEServiceTemplateApiEServiceTemplate, + getMockBffApiEServiceTemplate, getMockBffApiEServiceTemplateSeed, } from "../../mockUtils.js"; import { toBffCreatedEServiceTemplateVersion } from "../../../src/api/eserviceTemplateApiConverter.js"; @@ -16,7 +16,7 @@ import { toBffCreatedEServiceTemplateVersion } from "../../../src/api/eserviceTe describe("API POST /eservices/templates", () => { const mockEServiceTemplateSeed = getMockBffApiEServiceTemplateSeed(); const mockEServiceTemplateApiEServiceTemplate = - getMockBffApiEServiceTemplateApiEServiceTemplate(); + getMockBffApiEServiceTemplate(); const mockEServiceTemplate = toBffCreatedEServiceTemplateVersion( mockEServiceTemplateApiEServiceTemplate ); diff --git a/packages/backend-for-frontend/test/api/eserviceTemplateRouter/updateEServiceTemplatePersonalData.test.ts b/packages/backend-for-frontend/test/api/eserviceTemplateRouter/updateEServiceTemplatePersonalData.test.ts index 2422036a30..e16a951f3b 100644 --- a/packages/backend-for-frontend/test/api/eserviceTemplateRouter/updateEServiceTemplatePersonalData.test.ts +++ b/packages/backend-for-frontend/test/api/eserviceTemplateRouter/updateEServiceTemplatePersonalData.test.ts @@ -1,27 +1,43 @@ /* eslint-disable @typescript-eslint/explicit-function-return-type */ import { describe, it, expect, vi, beforeEach } from "vitest"; -import { EServiceTemplateId, generateId } from "pagopa-interop-models"; -import { generateToken } from "pagopa-interop-commons-test"; +import { + EServiceTemplate, + EServiceTemplateId, + EServiceTemplateVersion, + eserviceTemplateVersionState, + generateId, +} from "pagopa-interop-models"; +import { + generateToken, + getMockDocument, + getMockEServiceTemplate, + getMockEServiceTemplateVersion, +} from "pagopa-interop-commons-test"; import { authRole } from "pagopa-interop-commons"; import request from "supertest"; import { bffApi } from "pagopa-interop-api-clients"; import { api, clients } from "../../vitest.api.setup.js"; import { appBasePath } from "../../../src/config/appBasePath.js"; -import { getMockBffApiEServiceTemplatePersonalDataUpdateSeed } from "../../mockUtils.js"; +import { + getMockBffApiEServiceTemplatePersonaData, + getMockBffApiEServiceTemplatePersonalDataUpdateSeed, +} from "../../mockUtils.js"; describe("API POST /eservices/templates/:eServiceTemplateId/personalData", () => { - const mockEServiceTemplateId = generateId(); + const mockEServiceTemplate = { + ...getMockBffApiEServiceTemplatePersonaData(), + }; const mockEServiceTemplatePersonalDataUpdateSeed = getMockBffApiEServiceTemplatePersonalDataUpdateSeed(); beforeEach(() => { clients.eserviceTemplateProcessClient.updateEServiceTemplatePersonalDataAfterPublish = - vi.fn().mockResolvedValue(undefined); + vi.fn().mockResolvedValue(mockEServiceTemplate); }); const makeRequest = async ( token: string, - eServiceTemplateId: EServiceTemplateId = mockEServiceTemplateId, + eServiceTemplateId: EServiceTemplateId = mockEServiceTemplate.id, body: bffApi.EServiceTemplatePersonalDataUpdateSeed = mockEServiceTemplatePersonalDataUpdateSeed ) => request(api) diff --git a/packages/backend-for-frontend/test/mockUtils.ts b/packages/backend-for-frontend/test/mockUtils.ts index 8f1edbdc27..264c061e6c 100644 --- a/packages/backend-for-frontend/test/mockUtils.ts +++ b/packages/backend-for-frontend/test/mockUtils.ts @@ -641,8 +641,10 @@ export const getMockBffApiEServiceTemplateSeed = isSignalHubEnabled: generateMock(z.boolean().optional()), }); -export const getMockBffApiEServiceTemplateApiEServiceTemplate = - (): eserviceTemplateApi.EServiceTemplate => ({ +export const getMockBffApiEServiceTemplate = + (): eserviceTemplateApi.EServiceTemplate & { + id: EServiceTemplateId; + } => ({ id: generateId(), creatorId: generateId(), name: generateMock(z.string()), @@ -659,6 +661,14 @@ export const getMockBffApiEServiceTemplateApiEServiceTemplate = isSignalHubEnabled: generateMock(z.boolean().optional()), }); +export const getMockBffApiEServiceTemplatePersonaData = + (): eserviceTemplateApi.EServiceTemplate & { + id: EServiceTemplateId; + } => ({ + ...getMockBffApiEServiceTemplate(), + personalData: generateMock(z.boolean().optional()), + }); + export const getMockBffApiEServiceTemplateDetails = (): bffApi.EServiceTemplateDetails & { id: EServiceTemplateId } => ({ id: generateId(), From 804525a5e0a9201a61bcc82d117f7071640d00a2 Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Thu, 25 Sep 2025 14:39:25 +0200 Subject: [PATCH 089/180] test(backend-for-frontend): add getMockBffApiEServicePersonalData --- .../api/catalogRouter/updateEServicePersonalData.test.ts | 4 ++-- packages/backend-for-frontend/test/mockUtils.ts | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/backend-for-frontend/test/api/catalogRouter/updateEServicePersonalData.test.ts b/packages/backend-for-frontend/test/api/catalogRouter/updateEServicePersonalData.test.ts index 36d8581f1c..059026b8b6 100644 --- a/packages/backend-for-frontend/test/api/catalogRouter/updateEServicePersonalData.test.ts +++ b/packages/backend-for-frontend/test/api/catalogRouter/updateEServicePersonalData.test.ts @@ -8,14 +8,14 @@ import { bffApi } from "pagopa-interop-api-clients"; import { api, clients } from "../../vitest.api.setup.js"; import { getMockBffApiEServicePersonalDataUpdateSeed, - getMockCatalogApiEService, + getMockBffApiEServicePersonaData, } from "../../mockUtils.js"; import { appBasePath } from "../../../src/config/appBasePath.js"; describe("API POST /eservices/:eServiceId/personalData", () => { const mockEServicePersonalDataUpdateSeed = getMockBffApiEServicePersonalDataUpdateSeed(); - const mockEService = getMockCatalogApiEService(); + const mockEService = getMockBffApiEServicePersonaData(); const makeRequest = async ( token: string, diff --git a/packages/backend-for-frontend/test/mockUtils.ts b/packages/backend-for-frontend/test/mockUtils.ts index d96aec4a94..13ad0b141c 100644 --- a/packages/backend-for-frontend/test/mockUtils.ts +++ b/packages/backend-for-frontend/test/mockUtils.ts @@ -284,6 +284,13 @@ export const getMockCatalogApiEService = (): catalogApi.EService & { personalData: generateMock(z.boolean().optional()), }); +export const getMockBffApiEServicePersonaData = (): catalogApi.EService & { + id: EServiceId; +} => ({ + ...getMockCatalogApiEService(), + personalData: generateMock(z.boolean().optional()), +}); + export const getMockBffApiFileResource = (): bffApi.FileResource => ({ url: generateMock(z.string().url()), filename: generateMock(z.string()), From 6144843a24bdbc94927614ab5b2c350baa49991d Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Thu, 25 Sep 2025 14:41:22 +0200 Subject: [PATCH 090/180] chore(backend-for-frontend): remove unused imports --- .../updateEServiceTemplatePersonalData.test.ts | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/packages/backend-for-frontend/test/api/eserviceTemplateRouter/updateEServiceTemplatePersonalData.test.ts b/packages/backend-for-frontend/test/api/eserviceTemplateRouter/updateEServiceTemplatePersonalData.test.ts index e16a951f3b..9508c0acb6 100644 --- a/packages/backend-for-frontend/test/api/eserviceTemplateRouter/updateEServiceTemplatePersonalData.test.ts +++ b/packages/backend-for-frontend/test/api/eserviceTemplateRouter/updateEServiceTemplatePersonalData.test.ts @@ -1,18 +1,7 @@ /* eslint-disable @typescript-eslint/explicit-function-return-type */ import { describe, it, expect, vi, beforeEach } from "vitest"; -import { - EServiceTemplate, - EServiceTemplateId, - EServiceTemplateVersion, - eserviceTemplateVersionState, - generateId, -} from "pagopa-interop-models"; -import { - generateToken, - getMockDocument, - getMockEServiceTemplate, - getMockEServiceTemplateVersion, -} from "pagopa-interop-commons-test"; +import { EServiceTemplateId, generateId } from "pagopa-interop-models"; +import { generateToken } from "pagopa-interop-commons-test"; import { authRole } from "pagopa-interop-commons"; import request from "supertest"; import { bffApi } from "pagopa-interop-api-clients"; From ffea81129cdaf9bced6704ea7f97c7db174a3dfe Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 25 Sep 2025 15:02:46 +0200 Subject: [PATCH 091/180] Use renamed events --- .../agreement-outbound-writer/package.json | 2 +- packages/catalog-outbound-writer/package.json | 2 +- .../src/converters/toOutboundEventV2.ts | 2 +- .../src/consumerServiceV2.ts | 2 +- .../src/model/domain/toEvent.ts | 4 +-- .../src/services/catalogService.ts | 13 ++++---- ...icePersonalDataUpdatedAfterPublish.test.ts | 6 ++-- .../src/consumerServiceV2.ts | 2 +- ...catalogReadmodelWriter.integration.test.ts | 8 ++--- .../src/interfaceExporterV2.ts | 2 +- .../delegation-outbound-writer/package.json | 2 +- .../src/handlers/catalog/consumerServiceV2.ts | 2 +- .../package.json | 2 +- .../src/handlers/handleCatalogMessageV2.ts | 2 +- .../handlers/eservices/handleEserviceEvent.ts | 2 +- .../src/handlers/handleEServiceEvent.ts | 2 +- .../models/proto/v2/eservice/events.proto | 2 +- .../models/src/eservice/eserviceEvents.ts | 12 ++++---- .../notification-email-sender/src/index.ts | 2 +- .../catalogItemEventNotificationConverter.ts | 2 +- .../catalogItemEventNotificationMessage.ts | 2 +- packages/purpose-outbound-writer/package.json | 2 +- packages/tenant-outbound-writer/package.json | 2 +- pnpm-lock.yaml | 30 +++++++++---------- 24 files changed, 56 insertions(+), 53 deletions(-) diff --git a/packages/agreement-outbound-writer/package.json b/packages/agreement-outbound-writer/package.json index ad5d26942e..ef97cd461d 100644 --- a/packages/agreement-outbound-writer/package.json +++ b/packages/agreement-outbound-writer/package.json @@ -28,7 +28,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.6", + "@pagopa/interop-outbound-models": "1.6.8", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/packages/catalog-outbound-writer/package.json b/packages/catalog-outbound-writer/package.json index 5e1b744b1c..1065bfc7f7 100644 --- a/packages/catalog-outbound-writer/package.json +++ b/packages/catalog-outbound-writer/package.json @@ -28,7 +28,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.6", + "@pagopa/interop-outbound-models": "1.6.8", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/packages/catalog-outbound-writer/src/converters/toOutboundEventV2.ts b/packages/catalog-outbound-writer/src/converters/toOutboundEventV2.ts index d93b4df79f..33ed5cd629 100644 --- a/packages/catalog-outbound-writer/src/converters/toOutboundEventV2.ts +++ b/packages/catalog-outbound-writer/src/converters/toOutboundEventV2.ts @@ -97,7 +97,7 @@ export function toOutboundEventV2( { type: "EServiceNameUpdatedByTemplateUpdate" }, { type: "EServiceSignalHubEnabled" }, { type: "EServiceSignalHubDisabled" }, - { type: "EServicePersonalDataUpdatedAfterPublish" }, + { type: "EServicePersonalDataFlagUpdatedAfterPublication" }, (msg) => ({ event_version: msg.event_version, type: msg.type, diff --git a/packages/catalog-platformstate-writer/src/consumerServiceV2.ts b/packages/catalog-platformstate-writer/src/consumerServiceV2.ts index 658538b612..9ecd6cf018 100644 --- a/packages/catalog-platformstate-writer/src/consumerServiceV2.ts +++ b/packages/catalog-platformstate-writer/src/consumerServiceV2.ts @@ -303,7 +303,7 @@ export async function handleMessageV2( { type: "EServiceDescriptorDocumentDeletedByTemplateUpdate" }, { type: "EServiceSignalHubEnabled" }, { type: "EServiceSignalHubDisabled" }, - { type: "EServicePersonalDataUpdatedAfterPublish" }, + { type: "EServicePersonalDataFlagUpdatedAfterPublication" }, () => Promise.resolve() ) .exhaustive(); diff --git a/packages/catalog-process/src/model/domain/toEvent.ts b/packages/catalog-process/src/model/domain/toEvent.ts index f0d64e74a4..e733ebd415 100644 --- a/packages/catalog-process/src/model/domain/toEvent.ts +++ b/packages/catalog-process/src/model/domain/toEvent.ts @@ -861,7 +861,7 @@ export const toCreateEventEServiceSignalhubFlagDisabled = ( correlationId, }); -export const toCreateEventEServicePersonalDataUpdatedAfterPublish = ( +export const toCreateEventEServicePersonalDataFlagUpdatedAfterPublication = ( version: number, eservice: EService, correlationId: CorrelationId @@ -869,7 +869,7 @@ export const toCreateEventEServicePersonalDataUpdatedAfterPublish = ( streamId: eservice.id, version, event: { - type: "EServicePersonalDataUpdatedAfterPublish", + type: "EServicePersonalDataFlagUpdatedAfterPublication", event_version: 2, data: { eservice: toEServiceV2(eservice), diff --git a/packages/catalog-process/src/services/catalogService.ts b/packages/catalog-process/src/services/catalogService.ts index 1d7ed99ff5..5a9349548b 100644 --- a/packages/catalog-process/src/services/catalogService.ts +++ b/packages/catalog-process/src/services/catalogService.ts @@ -145,7 +145,7 @@ import { toCreateEventEServiceUpdated, toCreateEventEServiceSignalhubFlagEnabled, toCreateEventEServiceSignalhubFlagDisabled, - toCreateEventEServicePersonalDataUpdatedAfterPublish, + toCreateEventEServicePersonalDataFlagUpdatedAfterPublication, } from "../model/domain/toEvent.js"; import { getLatestDescriptor, @@ -3567,11 +3567,12 @@ export function catalogServiceBuilder( personalData, }; - const event = toCreateEventEServicePersonalDataUpdatedAfterPublish( - eservice.metadata.version, - updatedEservice, - correlationId - ); + const event = + toCreateEventEServicePersonalDataFlagUpdatedAfterPublication( + eservice.metadata.version, + updatedEservice, + correlationId + ); await repository.createEvent(event); diff --git a/packages/catalog-process/test/integration/updateEServicePersonalDataUpdatedAfterPublish.test.ts b/packages/catalog-process/test/integration/updateEServicePersonalDataUpdatedAfterPublish.test.ts index edc0e28a97..931fac4465 100644 --- a/packages/catalog-process/test/integration/updateEServicePersonalDataUpdatedAfterPublish.test.ts +++ b/packages/catalog-process/test/integration/updateEServicePersonalDataUpdatedAfterPublish.test.ts @@ -12,7 +12,7 @@ import { descriptorState, EService, toEServiceV2, - EServicePersonalDataUpdatedAfterPublishV2, + EServicePersonalDataFlagUpdatedAfterPublicationV2, operationForbidden, } from "pagopa-interop-models"; import { expect, describe, it } from "vitest"; @@ -58,12 +58,12 @@ describe("update E-service personalData flag for an already created E-service", expect(writtenEvent).toMatchObject({ stream_id: eservice.id, version: "1", - type: "EServicePersonalDataUpdatedAfterPublish", + type: "EServicePersonalDataFlagUpdatedAfterPublication", event_version: 2, }); const writtenPayload = decodeProtobufPayload({ - messageType: EServicePersonalDataUpdatedAfterPublishV2, + messageType: EServicePersonalDataFlagUpdatedAfterPublicationV2, payload: writtenEvent.data, }); diff --git a/packages/catalog-readmodel-writer-sql/src/consumerServiceV2.ts b/packages/catalog-readmodel-writer-sql/src/consumerServiceV2.ts index 5fbb0ade53..7060f981f0 100644 --- a/packages/catalog-readmodel-writer-sql/src/consumerServiceV2.ts +++ b/packages/catalog-readmodel-writer-sql/src/consumerServiceV2.ts @@ -59,7 +59,7 @@ export async function handleMessageV2( { type: "EServiceDescriptorDocumentDeletedByTemplateUpdate" }, { type: "EServiceSignalHubEnabled" }, { type: "EServiceSignalHubDisabled" }, - { type: "EServicePersonalDataUpdatedAfterPublish" }, + { type: "EServicePersonalDataFlagUpdatedAfterPublication" }, async (message) => { const eservice = message.data.eservice; if (!eservice) { diff --git a/packages/catalog-readmodel-writer-sql/test/catalogReadmodelWriter.integration.test.ts b/packages/catalog-readmodel-writer-sql/test/catalogReadmodelWriter.integration.test.ts index d0bec28ed9..1497445b44 100644 --- a/packages/catalog-readmodel-writer-sql/test/catalogReadmodelWriter.integration.test.ts +++ b/packages/catalog-readmodel-writer-sql/test/catalogReadmodelWriter.integration.test.ts @@ -39,7 +39,7 @@ import { EServiceDraftDescriptorUpdatedV2, EServiceEventEnvelope, EServiceNameUpdatedV2, - EServicePersonalDataUpdatedAfterPublishV2, + EServicePersonalDataFlagUpdatedAfterPublicationV2, EServiceRiskAnalysisAddedV1, EServiceRiskAnalysisAddedV2, EServiceRiskAnalysisDeletedV1, @@ -1615,7 +1615,7 @@ describe("database test", async () => { expect(retrievedEservice?.metadata).toEqual({ version: 2 }); }); - it("EServicePersonalDataUpdatedAfterPublish", async () => { + it("EServicePersonalDataFlagUpdatedAfterPublication", async () => { const publishedDescriptor: Descriptor = { ...getMockDescriptor(), interface: getMockDocument(), @@ -1631,14 +1631,14 @@ describe("database test", async () => { ...eservice, personalData: true, }; - const payload: EServicePersonalDataUpdatedAfterPublishV2 = { + const payload: EServicePersonalDataFlagUpdatedAfterPublicationV2 = { eservice: toEServiceV2(updatedEService), }; const message: EServiceEventEnvelope = { sequence_num: 1, stream_id: mockEService.id, version: 2, - type: "EServicePersonalDataUpdatedAfterPublish", + type: "EServicePersonalDataFlagUpdatedAfterPublication", event_version: 2, data: payload, log_date: new Date(), diff --git a/packages/datalake-interface-exporter/src/interfaceExporterV2.ts b/packages/datalake-interface-exporter/src/interfaceExporterV2.ts index 44b62f79fd..9d0a31b669 100644 --- a/packages/datalake-interface-exporter/src/interfaceExporterV2.ts +++ b/packages/datalake-interface-exporter/src/interfaceExporterV2.ts @@ -74,7 +74,7 @@ export async function exportInterfaceV2( { type: "EServiceDescriptorDocumentDeletedByTemplateUpdate" }, { type: "EServiceSignalHubEnabled" }, { type: "EServiceSignalHubDisabled" }, - { type: "EServicePersonalDataUpdatedAfterPublish" }, + { type: "EServicePersonalDataFlagUpdatedAfterPublication" }, () => undefined ) .exhaustive(); diff --git a/packages/delegation-outbound-writer/package.json b/packages/delegation-outbound-writer/package.json index 19d84c84b8..0b1c0d0cd3 100644 --- a/packages/delegation-outbound-writer/package.json +++ b/packages/delegation-outbound-writer/package.json @@ -27,7 +27,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.6", + "@pagopa/interop-outbound-models": "1.6.8", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/packages/domains-analytics-writer/src/handlers/catalog/consumerServiceV2.ts b/packages/domains-analytics-writer/src/handlers/catalog/consumerServiceV2.ts index f4afb62d5e..623a7a78a1 100644 --- a/packages/domains-analytics-writer/src/handlers/catalog/consumerServiceV2.ts +++ b/packages/domains-analytics-writer/src/handlers/catalog/consumerServiceV2.ts @@ -78,7 +78,7 @@ export async function handleCatalogMessageV2( "EServiceDraftDescriptorDeleted", "EServiceSignalHubEnabled", "EServiceSignalHubDisabled", - "EServicePersonalDataUpdatedAfterPublish" + "EServicePersonalDataFlagUpdatedAfterPublication" ), }, (msg) => { diff --git a/packages/eservice-template-outbound-writer/package.json b/packages/eservice-template-outbound-writer/package.json index 0445198b0f..e0d7c22de7 100644 --- a/packages/eservice-template-outbound-writer/package.json +++ b/packages/eservice-template-outbound-writer/package.json @@ -27,7 +27,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.6", + "@pagopa/interop-outbound-models": "1.6.8", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/packages/events-signer/src/handlers/handleCatalogMessageV2.ts b/packages/events-signer/src/handlers/handleCatalogMessageV2.ts index 7c068c5610..c8ae8a34e5 100644 --- a/packages/events-signer/src/handlers/handleCatalogMessageV2.ts +++ b/packages/events-signer/src/handlers/handleCatalogMessageV2.ts @@ -103,7 +103,7 @@ export const handleCatalogMessageV2 = async ( "EServiceDescriptorDocumentDeletedByTemplateUpdate", "EServiceSignalHubEnabled", "EServiceSignalHubDisabled", - "EServicePersonalDataUpdatedAfterPublish" + "EServicePersonalDataFlagUpdatedAfterPublication" ), }, (event) => { diff --git a/packages/in-app-notification-dispatcher/src/handlers/eservices/handleEserviceEvent.ts b/packages/in-app-notification-dispatcher/src/handlers/eservices/handleEserviceEvent.ts index 62b1197214..068448d102 100644 --- a/packages/in-app-notification-dispatcher/src/handlers/eservices/handleEserviceEvent.ts +++ b/packages/in-app-notification-dispatcher/src/handlers/eservices/handleEserviceEvent.ts @@ -92,7 +92,7 @@ export async function handleEServiceEvent( "EServiceIsClientAccessDelegableDisabled", "EServiceSignalHubEnabled", "EServiceSignalHubDisabled", - "EServicePersonalDataUpdatedAfterPublish" + "EServicePersonalDataFlagUpdatedAfterPublication" ), }, () => { diff --git a/packages/m2m-event-dispatcher/src/handlers/handleEServiceEvent.ts b/packages/m2m-event-dispatcher/src/handlers/handleEServiceEvent.ts index ba7f5f1cdd..a97efbd0b9 100644 --- a/packages/m2m-event-dispatcher/src/handlers/handleEServiceEvent.ts +++ b/packages/m2m-event-dispatcher/src/handlers/handleEServiceEvent.ts @@ -55,7 +55,7 @@ export async function handleEServiceEvent( "EServiceDescriptorDocumentUpdatedByTemplateUpdate", "EServiceSignalHubEnabled", "EServiceSignalHubDisabled", - "EServicePersonalDataUpdatedAfterPublish" + "EServicePersonalDataFlagUpdatedAfterPublication" ), }, () => Promise.resolve(void 0) diff --git a/packages/models/proto/v2/eservice/events.proto b/packages/models/proto/v2/eservice/events.proto index 85a6d92e25..ede176e0ed 100644 --- a/packages/models/proto/v2/eservice/events.proto +++ b/packages/models/proto/v2/eservice/events.proto @@ -211,6 +211,6 @@ message EServiceSignalHubDisabledV2 { EServiceV2 eservice = 1; } -message EServicePersonalDataUpdatedAfterPublishV2 { +message EServicePersonalDataFlagUpdatedAfterPublicationV2 { EServiceV2 eservice = 1; } diff --git a/packages/models/src/eservice/eserviceEvents.ts b/packages/models/src/eservice/eserviceEvents.ts index 1c5e8cbd75..c2b5e28aa6 100644 --- a/packages/models/src/eservice/eserviceEvents.ts +++ b/packages/models/src/eservice/eserviceEvents.ts @@ -60,7 +60,7 @@ import { EServiceDescriptorAgreementApprovalPolicyUpdatedV2, EServiceSignalHubEnabledV2, EServiceSignalHubDisabledV2, - EServicePersonalDataUpdatedAfterPublishV2, + EServicePersonalDataFlagUpdatedAfterPublicationV2, } from "../gen/v2/eservice/events.js"; export function catalogEventToBinaryData(event: EServiceEvent): Uint8Array { @@ -254,8 +254,10 @@ export function catalogEventToBinaryDataV2(event: EServiceEventV2): Uint8Array { .with({ type: "EServiceSignalHubDisabled" }, ({ data }) => EServiceSignalHubDisabledV2.toBinary(data) ) - .with({ type: "EServicePersonalDataUpdatedAfterPublish" }, ({ data }) => - EServicePersonalDataUpdatedAfterPublishV2.toBinary(data) + .with( + { type: "EServicePersonalDataFlagUpdatedAfterPublication" }, + ({ data }) => + EServicePersonalDataFlagUpdatedAfterPublicationV2.toBinary(data) ) .exhaustive(); } @@ -544,8 +546,8 @@ export const EServiceEventV2 = z.discriminatedUnion("type", [ }), z.object({ event_version: z.literal(2), - type: z.literal("EServicePersonalDataUpdatedAfterPublish"), - data: protobufDecoder(EServicePersonalDataUpdatedAfterPublishV2), + type: z.literal("EServicePersonalDataFlagUpdatedAfterPublication"), + data: protobufDecoder(EServicePersonalDataFlagUpdatedAfterPublicationV2), }), ]); export type EServiceEventV2 = z.infer; diff --git a/packages/notification-email-sender/src/index.ts b/packages/notification-email-sender/src/index.ts index ca6eec9bc9..f986248b5e 100644 --- a/packages/notification-email-sender/src/index.ts +++ b/packages/notification-email-sender/src/index.ts @@ -162,7 +162,7 @@ export async function handleCatalogMessage( "EServiceDescriptorDocumentUpdatedByTemplateUpdate", "EServiceSignalHubEnabled", "EServiceSignalHubDisabled", - "EServicePersonalDataUpdatedAfterPublish" + "EServicePersonalDataFlagUpdatedAfterPublication" ), }, () => { diff --git a/packages/notifier-seeder/src/models/catalog/catalogItemEventNotificationConverter.ts b/packages/notifier-seeder/src/models/catalog/catalogItemEventNotificationConverter.ts index d20b8386de..3d5f6b4f81 100644 --- a/packages/notifier-seeder/src/models/catalog/catalogItemEventNotificationConverter.ts +++ b/packages/notifier-seeder/src/models/catalog/catalogItemEventNotificationConverter.ts @@ -100,7 +100,7 @@ export const toCatalogItemEventNotification = ( { type: "EServiceSignalHubEnabled" }, // CatalogItemV1UpdatedV1 { type: "EServiceSignalHubDisabled" }, // CatalogItemV1UpdatedV1 { type: "EServiceNameUpdatedByTemplateUpdate" }, - { type: "EServicePersonalDataUpdatedAfterPublish" }, + { type: "EServicePersonalDataFlagUpdatedAfterPublication" }, (e): CatalogItemNotification => ({ catalogItem: getCatalogItem(e), }) diff --git a/packages/notifier-seeder/src/models/catalog/catalogItemEventNotificationMessage.ts b/packages/notifier-seeder/src/models/catalog/catalogItemEventNotificationMessage.ts index 8d8207b251..8cba6ff734 100644 --- a/packages/notifier-seeder/src/models/catalog/catalogItemEventNotificationMessage.ts +++ b/packages/notifier-seeder/src/models/catalog/catalogItemEventNotificationMessage.ts @@ -21,7 +21,7 @@ export const eventV2TypeMapper = ( "EServiceDescriptionUpdatedByTemplateUpdate", "EServiceSignalHubEnabled", "EServiceSignalHubDisabled", - "EServicePersonalDataUpdatedAfterPublish", + "EServicePersonalDataFlagUpdatedAfterPublication", () => "catalog_item_updated" ) .with( diff --git a/packages/purpose-outbound-writer/package.json b/packages/purpose-outbound-writer/package.json index 17e9a4d6d1..7e645f66b0 100644 --- a/packages/purpose-outbound-writer/package.json +++ b/packages/purpose-outbound-writer/package.json @@ -28,7 +28,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.6", + "@pagopa/interop-outbound-models": "1.6.8", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/packages/tenant-outbound-writer/package.json b/packages/tenant-outbound-writer/package.json index 2b9d649e28..c32324d0b9 100644 --- a/packages/tenant-outbound-writer/package.json +++ b/packages/tenant-outbound-writer/package.json @@ -28,7 +28,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.6", + "@pagopa/interop-outbound-models": "1.6.8", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 293a448dc7..20a2180042 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -40,8 +40,8 @@ importers: packages/agreement-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.6 - version: 1.6.6 + specifier: 1.6.8 + version: 1.6.8 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -1184,8 +1184,8 @@ importers: packages/catalog-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.6 - version: 1.6.6 + specifier: 1.6.8 + version: 1.6.8 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -2118,8 +2118,8 @@ importers: packages/delegation-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.6 - version: 1.6.6 + specifier: 1.6.8 + version: 1.6.8 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -2694,8 +2694,8 @@ importers: packages/eservice-template-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.6 - version: 1.6.6 + specifier: 1.6.8 + version: 1.6.8 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -4444,8 +4444,8 @@ importers: packages/purpose-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.6 - version: 1.6.6 + specifier: 1.6.8 + version: 1.6.8 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -5140,8 +5140,8 @@ importers: packages/tenant-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.6 - version: 1.6.6 + specifier: 1.6.8 + version: 1.6.8 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -6850,8 +6850,8 @@ packages: '@pagopa/eslint-config@3.0.0': resolution: {integrity: sha512-eYIPdiuYRbRPR5k0OuteRNqYb0Z2nfJ/lZohejB7ylfBeSDWwkaV8Z19AXP4RymE6oEesyPDZ6i0yNaE9tQrHw==} - '@pagopa/interop-outbound-models@1.6.6': - resolution: {integrity: sha512-TPoI/RPRl5wFH1ui6eK4KdAEC+gq4tN2svifSSBLQBdQB7FccxO1kYBs+0ytCRJp8u/T48EbsT+d9wyYvlwHfw==} + '@pagopa/interop-outbound-models@1.6.8': + resolution: {integrity: sha512-iy4lwWH1GmwpikG4j+J8JO29dhlT4yoSKcYXi101XsPm6AK/3+DS3Dvf6rddSGzLBBkqTM6sHjgqLTfjnGgsig==} '@protobuf-ts/plugin-framework@2.9.4': resolution: {integrity: sha512-9nuX1kjdMliv+Pes8dQCKyVhjKgNNfwxVHg+tx3fLXSfZZRcUHMc1PMwB9/vTvc6gBKt9QGz5ERqSqZc0++E9A==} @@ -13855,7 +13855,7 @@ snapshots: - tsutils - typescript - '@pagopa/interop-outbound-models@1.6.6': + '@pagopa/interop-outbound-models@1.6.8': dependencies: '@protobuf-ts/runtime': 2.9.4 ts-pattern: 5.2.0 From 5b2ba21c2198e92042ca63b629e6596057a257e1 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 25 Sep 2025 15:08:01 +0200 Subject: [PATCH 092/180] Rename error --- packages/catalog-process/src/model/domain/errors.ts | 8 ++++---- packages/catalog-process/src/services/catalogService.ts | 4 ++-- packages/catalog-process/src/utilities/errorMappers.ts | 2 +- .../catalog-process/test/api/publishDescriptor.test.ts | 4 ++-- .../test/integration/publishDescriptor.test.ts | 8 +++----- 5 files changed, 12 insertions(+), 14 deletions(-) diff --git a/packages/catalog-process/src/model/domain/errors.ts b/packages/catalog-process/src/model/domain/errors.ts index e25e2b886f..11fceb3791 100644 --- a/packages/catalog-process/src/model/domain/errors.ts +++ b/packages/catalog-process/src/model/domain/errors.ts @@ -56,7 +56,7 @@ export const errorCodes = { checksumDuplicate: "0040", attributeDuplicatedInGroup: "0041", eservicePersonalDataCanOnlyBeSetOnce: "0042", - eservicePersonalDataMustBeSet: "0043", + missingPersonalDataFlag: "0043", }; export type ErrorCodes = keyof typeof errorCodes; @@ -488,13 +488,13 @@ export function eservicePersonalDataCanOnlyBeSetOnce( }); } -export function eservicePersonalDataMustBeSet( +export function missingPersonalDataFlag( eserviceId: EServiceId, descriptorId: DescriptorId ): ApiError { return new ApiError({ detail: `Descriptor ${descriptorId} in eservice ${eserviceId} can't be published because personalData flag must be set for the eservice`, - code: "eservicePersonalDataMustBeSet", - title: "EService personalData must be set before publication", + code: "missingPersonalDataFlag", + title: "EService personalData flag must be set before publication", }); } diff --git a/packages/catalog-process/src/services/catalogService.ts b/packages/catalog-process/src/services/catalogService.ts index 9f8ef08f2e..82ea543438 100644 --- a/packages/catalog-process/src/services/catalogService.ts +++ b/packages/catalog-process/src/services/catalogService.ts @@ -101,7 +101,7 @@ import { checksumDuplicate, attributeDuplicatedInGroup, eservicePersonalDataCanOnlyBeSetOnce, - eservicePersonalDataMustBeSet, + missingPersonalDataFlag, } from "../model/domain/errors.js"; import { ApiGetEServicesFilters, Consumer } from "../model/domain/models.js"; import { @@ -1635,7 +1635,7 @@ export function catalogServiceBuilder( config.featureFlagEservicePersonalData && eservice.data.personalData === undefined ) { - throw eservicePersonalDataMustBeSet(eserviceId, descriptorId); + throw missingPersonalDataFlag(eserviceId, descriptorId); } if (producerDelegation) { diff --git a/packages/catalog-process/src/utilities/errorMappers.ts b/packages/catalog-process/src/utilities/errorMappers.ts index c4872b13a5..aa144928d2 100644 --- a/packages/catalog-process/src/utilities/errorMappers.ts +++ b/packages/catalog-process/src/utilities/errorMappers.ts @@ -297,7 +297,7 @@ export const publishDescriptorErrorMapper = ( "riskAnalysisNotValid", "notValidDescriptor", "audienceCannotBeEmpty", - "eservicePersonalDataMustBeSet", + "missingPersonalDataFlag", () => HTTP_STATUS_BAD_REQUEST ) .with("operationForbidden", () => HTTP_STATUS_FORBIDDEN) diff --git a/packages/catalog-process/test/api/publishDescriptor.test.ts b/packages/catalog-process/test/api/publishDescriptor.test.ts index 302a992815..9976d85717 100644 --- a/packages/catalog-process/test/api/publishDescriptor.test.ts +++ b/packages/catalog-process/test/api/publishDescriptor.test.ts @@ -23,7 +23,7 @@ import { eServiceDescriptorNotFound, eServiceDescriptorWithoutInterface, eServiceNotFound, - eservicePersonalDataMustBeSet, + missingPersonalDataFlag, eServiceRiskAnalysisIsRequired, notValidDescriptorState, riskAnalysisNotValid, @@ -122,7 +122,7 @@ describe("API /eservices/{eServiceId}/descriptors/{descriptorId}/publish authori expectedStatus: 400, }, { - error: eservicePersonalDataMustBeSet(mockEService.id, descriptor.id), + error: missingPersonalDataFlag(mockEService.id, descriptor.id), expectedStatus: 400, }, ])( diff --git a/packages/catalog-process/test/integration/publishDescriptor.test.ts b/packages/catalog-process/test/integration/publishDescriptor.test.ts index 8e9a9a3536..f63e631338 100644 --- a/packages/catalog-process/test/integration/publishDescriptor.test.ts +++ b/packages/catalog-process/test/integration/publishDescriptor.test.ts @@ -40,7 +40,7 @@ import { eServiceRiskAnalysisIsRequired, riskAnalysisNotValid, audienceCannotBeEmpty, - eservicePersonalDataMustBeSet, + missingPersonalDataFlag, } from "../../src/model/domain/errors.js"; import { addOneEService, @@ -730,7 +730,7 @@ describe("publish descriptor", () => { ).rejects.toThrowError(audienceCannotBeEmpty(descriptor.id)); }); - it("should throw eservicePersonalDataMustBeSet if the eservice has personalData undefined", async () => { + it("should throw missingPersonalDataFlag if the eservice has personalData undefined", async () => { const descriptor: Descriptor = { ...mockDescriptor, state: descriptorState.draft, @@ -751,8 +751,6 @@ describe("publish descriptor", () => { descriptor.id, getMockContext({ authData: getMockAuthData(eservice.producerId) }) ) - ).rejects.toThrowError( - eservicePersonalDataMustBeSet(eservice.id, descriptor.id) - ); + ).rejects.toThrowError(missingPersonalDataFlag(eservice.id, descriptor.id)); }); }); From 3d3590d2cab3b776adead0bef8f6ac9fa1609014 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 25 Sep 2025 15:14:54 +0200 Subject: [PATCH 093/180] Fix test title --- .../eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts b/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts index 76fd00b02c..45d63d5ffb 100644 --- a/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts +++ b/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts @@ -905,7 +905,7 @@ describe("eserviceTemplateUpdaterConsumerServiceV2", () => { }); }); - it("The consumer should call the updateTemplateInstanceDataPersonalFlag route on EServiceTemplatePersonalDataUpdatedAfterPublish event", async () => { + it("The consumer should call the updateTemplateInstancePersonalDataFlag route on EServiceTemplatePersonalDataUpdatedAfterPublish event", async () => { const mockTemplate: EServiceTemplate = { ...eserviceTemplate, personalData: true, From 04e58feb8ae7aced218f8c44e4559b7ddd19eaac Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 25 Sep 2025 15:15:19 +0200 Subject: [PATCH 094/180] Rename event --- packages/models/proto/v2/eservice/events.proto | 2 +- packages/models/src/eservice/eserviceEvents.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/models/proto/v2/eservice/events.proto b/packages/models/proto/v2/eservice/events.proto index 20b306a5cb..69844caf86 100644 --- a/packages/models/proto/v2/eservice/events.proto +++ b/packages/models/proto/v2/eservice/events.proto @@ -215,6 +215,6 @@ message EServicePersonalDataUpdatedAfterPublishV2 { EServiceV2 eservice = 1; } -message EServicePersonalDataUpdatedByTemplateUpdateV2 { +message EServicePersonalDataFlagUpdatedByTemplateUpdateV2 { EServiceV2 eservice = 1; } diff --git a/packages/models/src/eservice/eserviceEvents.ts b/packages/models/src/eservice/eserviceEvents.ts index 3a5a78d6c7..495ef1f34e 100644 --- a/packages/models/src/eservice/eserviceEvents.ts +++ b/packages/models/src/eservice/eserviceEvents.ts @@ -61,7 +61,7 @@ import { EServiceSignalHubEnabledV2, EServiceSignalHubDisabledV2, EServicePersonalDataUpdatedAfterPublishV2, - EServicePersonalDataUpdatedByTemplateUpdateV2, + EServicePersonalDataFlagUpdatedByTemplateUpdateV2, } from "../gen/v2/eservice/events.js"; export function catalogEventToBinaryData(event: EServiceEvent): Uint8Array { @@ -259,7 +259,7 @@ export function catalogEventToBinaryDataV2(event: EServiceEventV2): Uint8Array { EServicePersonalDataUpdatedAfterPublishV2.toBinary(data) ) .with({ type: "EServicePersonalDataUpdatedByTemplateUpdate" }, ({ data }) => - EServicePersonalDataUpdatedByTemplateUpdateV2.toBinary(data) + EServicePersonalDataFlagUpdatedByTemplateUpdateV2.toBinary(data) ) .exhaustive(); } @@ -554,7 +554,7 @@ export const EServiceEventV2 = z.discriminatedUnion("type", [ z.object({ event_version: z.literal(2), type: z.literal("EServicePersonalDataUpdatedByTemplateUpdate"), - data: protobufDecoder(EServicePersonalDataUpdatedByTemplateUpdateV2), + data: protobufDecoder(EServicePersonalDataFlagUpdatedByTemplateUpdateV2), }), ]); export type EServiceEventV2 = z.infer; From 8c5c2114ad00414178cc644c00423a56909860fe Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 25 Sep 2025 15:18:01 +0200 Subject: [PATCH 095/180] Renaming --- packages/catalog-process/src/model/domain/toEvent.ts | 2 +- packages/catalog-process/src/services/catalogService.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/catalog-process/src/model/domain/toEvent.ts b/packages/catalog-process/src/model/domain/toEvent.ts index 4c2e66dad5..516e2f1a53 100644 --- a/packages/catalog-process/src/model/domain/toEvent.ts +++ b/packages/catalog-process/src/model/domain/toEvent.ts @@ -702,7 +702,7 @@ export const toCreateEventEServiceDescriptionUpdatedByTemplateUpdate = ( correlationId, }); -export const toCreateEventEServicePersonalDataUpdatedByTemplateUpdate = ( +export const toCreateEventEServicePersonalDataFlagUpdatedByTemplateUpdate = ( version: number, eservice: EService, correlationId: CorrelationId diff --git a/packages/catalog-process/src/services/catalogService.ts b/packages/catalog-process/src/services/catalogService.ts index 700b97045d..0948f09cb9 100644 --- a/packages/catalog-process/src/services/catalogService.ts +++ b/packages/catalog-process/src/services/catalogService.ts @@ -147,7 +147,7 @@ import { toCreateEventEServiceSignalhubFlagEnabled, toCreateEventEServiceSignalhubFlagDisabled, toCreateEventEServicePersonalDataUpdatedAfterPublish, - toCreateEventEServicePersonalDataUpdatedByTemplateUpdate, + toCreateEventEServicePersonalDataFlagUpdatedByTemplateUpdate, } from "../model/domain/toEvent.js"; import { getLatestDescriptor, @@ -2936,7 +2936,7 @@ export function catalogServiceBuilder( personalData, }; await repository.createEvent( - toCreateEventEServicePersonalDataUpdatedByTemplateUpdate( + toCreateEventEServicePersonalDataFlagUpdatedByTemplateUpdate( eservice.metadata.version, updatedEservice, correlationId From 4d51dfa2e7e8b5eb49406fef342dfe332a5894e9 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 25 Sep 2025 15:20:32 +0200 Subject: [PATCH 096/180] Renaming --- packages/api-clients/open-api/bffApi.yml | 2 +- packages/api-clients/open-api/catalogApi.yml | 2 +- .../src/services/catalogService.ts | 2 +- .../catalogRouter/updateEServicePersonalData.test.ts | 5 ++--- packages/catalog-process/src/routers/EServiceRouter.ts | 2 +- .../catalog-process/src/services/catalogService.ts | 2 +- .../test/api/updateEServicePersonalData.test.ts | 4 ++-- ...dateEServicePersonalDataUpdatedAfterPublish.test.ts | 10 +++++----- 8 files changed, 14 insertions(+), 15 deletions(-) diff --git a/packages/api-clients/open-api/bffApi.yml b/packages/api-clients/open-api/bffApi.yml index deff818b0d..ff44590089 100644 --- a/packages/api-clients/open-api/bffApi.yml +++ b/packages/api-clients/open-api/bffApi.yml @@ -5945,7 +5945,7 @@ paths: tags: - eservices summary: Set personalData flag for published eservices - operationId: updateEServicePersonalDataAfterPublish + operationId: updateEServicePersonalDataFlagAfterPublication parameters: - name: eServiceId in: path diff --git a/packages/api-clients/open-api/catalogApi.yml b/packages/api-clients/open-api/catalogApi.yml index bfaf26e7a5..e72377a0a0 100644 --- a/packages/api-clients/open-api/catalogApi.yml +++ b/packages/api-clients/open-api/catalogApi.yml @@ -1977,7 +1977,7 @@ paths: tags: - process summary: Set personalData flag for published eservices - operationId: updateEServicePersonalDataAfterPublish + operationId: updateEServicePersonalDataFlagAfterPublication parameters: - name: eServiceId in: path diff --git a/packages/backend-for-frontend/src/services/catalogService.ts b/packages/backend-for-frontend/src/services/catalogService.ts index de1f406243..fdb1e647d6 100644 --- a/packages/backend-for-frontend/src/services/catalogService.ts +++ b/packages/backend-for-frontend/src/services/catalogService.ts @@ -606,7 +606,7 @@ export function catalogServiceBuilder( logger.info( `Set personal flag for E-Service with id = ${eServiceId} to ${personalDataSeed.personalData}` ); - await catalogProcessClient.updateEServicePersonalDataAfterPublish( + await catalogProcessClient.updateEServicePersonalDataFlagAfterPublication( personalDataSeed, { headers, diff --git a/packages/backend-for-frontend/test/api/catalogRouter/updateEServicePersonalData.test.ts b/packages/backend-for-frontend/test/api/catalogRouter/updateEServicePersonalData.test.ts index 059026b8b6..9def68c3df 100644 --- a/packages/backend-for-frontend/test/api/catalogRouter/updateEServicePersonalData.test.ts +++ b/packages/backend-for-frontend/test/api/catalogRouter/updateEServicePersonalData.test.ts @@ -29,9 +29,8 @@ describe("API POST /eservices/:eServiceId/personalData", () => { .send(body); beforeEach(() => { - clients.catalogProcessClient.updateEServicePersonalDataAfterPublish = vi - .fn() - .mockResolvedValue(mockEService); + clients.catalogProcessClient.updateEServicePersonalDataFlagAfterPublication = + vi.fn().mockResolvedValue(mockEService); }); it("Should return 204 if no error is thrown", async () => { diff --git a/packages/catalog-process/src/routers/EServiceRouter.ts b/packages/catalog-process/src/routers/EServiceRouter.ts index 532178abc5..1c7520091a 100644 --- a/packages/catalog-process/src/routers/EServiceRouter.ts +++ b/packages/catalog-process/src/routers/EServiceRouter.ts @@ -1481,7 +1481,7 @@ const eservicesRouter = ( } const updatedEService = - await catalogService.updateEServicePersonalDataAfterPublish( + await catalogService.updateEServicePersonalDataFlagAfterPublication( unsafeBrandId(req.params.eServiceId), req.body.personalData, ctx diff --git a/packages/catalog-process/src/services/catalogService.ts b/packages/catalog-process/src/services/catalogService.ts index 3794cd4fd2..5dc4acd016 100644 --- a/packages/catalog-process/src/services/catalogService.ts +++ b/packages/catalog-process/src/services/catalogService.ts @@ -3540,7 +3540,7 @@ export function catalogServiceBuilder( return updatedDescriptor; }, - async updateEServicePersonalDataAfterPublish( + async updateEServicePersonalDataFlagAfterPublication( eserviceId: EServiceId, personalData: boolean, { authData, correlationId, logger }: WithLogger> diff --git a/packages/catalog-process/test/api/updateEServicePersonalData.test.ts b/packages/catalog-process/test/api/updateEServicePersonalData.test.ts index 42ae77b2d4..8b09f17724 100644 --- a/packages/catalog-process/test/api/updateEServicePersonalData.test.ts +++ b/packages/catalog-process/test/api/updateEServicePersonalData.test.ts @@ -46,7 +46,7 @@ describe("API /eservices/{eServiceId}/personalData authorization test", () => { personalData, }; - catalogService.updateEServicePersonalDataAfterPublish = vi + catalogService.updateEServicePersonalDataFlagAfterPublication = vi .fn() .mockResolvedValue(serviceResponse); @@ -98,7 +98,7 @@ describe("API /eservices/{eServiceId}/personalData authorization test", () => { ])( "Should return $expectedStatus for $error.code", async ({ error, expectedStatus }) => { - catalogService.updateEServicePersonalDataAfterPublish = vi + catalogService.updateEServicePersonalDataFlagAfterPublication = vi .fn() .mockRejectedValue(error); diff --git a/packages/catalog-process/test/integration/updateEServicePersonalDataUpdatedAfterPublish.test.ts b/packages/catalog-process/test/integration/updateEServicePersonalDataUpdatedAfterPublish.test.ts index 931fac4465..34cbd88ceb 100644 --- a/packages/catalog-process/test/integration/updateEServicePersonalDataUpdatedAfterPublish.test.ts +++ b/packages/catalog-process/test/integration/updateEServicePersonalDataUpdatedAfterPublish.test.ts @@ -43,7 +43,7 @@ describe("update E-service personalData flag for an already created E-service", const newPersonalDataValue = true; const returnedEService = - await catalogService.updateEServicePersonalDataAfterPublish( + await catalogService.updateEServicePersonalDataFlagAfterPublication( eservice.id, newPersonalDataValue, getMockContext({ authData: getMockAuthData(eservice.producerId) }) @@ -91,7 +91,7 @@ describe("update E-service personalData flag for an already created E-service", await addOneEService(eservice); await expect( - catalogService.updateEServicePersonalDataAfterPublish( + catalogService.updateEServicePersonalDataFlagAfterPublication( eservice.id, newPersonalDataValue, getMockContext({ authData: getMockAuthData(eservice.producerId) }) @@ -105,7 +105,7 @@ describe("update E-service personalData flag for an already created E-service", async (personalDataFlag) => { const eservice = getMockEService(); expect( - catalogService.updateEServicePersonalDataAfterPublish( + catalogService.updateEServicePersonalDataFlagAfterPublication( eservice.id, personalDataFlag, getMockContext({ authData: getMockAuthData(eservice.producerId) }) @@ -120,7 +120,7 @@ describe("update E-service personalData flag for an already created E-service", const eservice = getMockEService(); await addOneEService(eservice); expect( - catalogService.updateEServicePersonalDataAfterPublish( + catalogService.updateEServicePersonalDataFlagAfterPublication( eservice.id, personalDataFlag, getMockContext({}) @@ -139,7 +139,7 @@ describe("update E-service personalData flag for an already created E-service", await addOneEService(eservice); expect( - catalogService.updateEServicePersonalDataAfterPublish( + catalogService.updateEServicePersonalDataFlagAfterPublication( eservice.id, personalDataFlag, getMockContext({ authData: getMockAuthData(eservice.producerId) }) From 1e076d1cb5524a7312dffa8612653a09e79c716a Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 25 Sep 2025 15:36:56 +0200 Subject: [PATCH 097/180] Rename event --- .../eservice-template/consumerServiceV2.ts | 2 +- ...mplateInstancesUpdaterConsumerServiceV2.ts | 2 +- ...eInstancesUpdaterConsumerServiceV2.test.ts | 2 +- .../src/model/domain/toEvent.ts | 31 ++++++++++--------- .../src/services/eserviceTemplateService.ts | 4 +-- .../src/consumerServiceV2.ts | 2 +- ...emplateReadmodelWriter.integration.test.ts | 4 +-- .../proto/v2/eservice-template/events.proto | 2 +- 8 files changed, 25 insertions(+), 24 deletions(-) diff --git a/packages/domains-analytics-writer/src/handlers/eservice-template/consumerServiceV2.ts b/packages/domains-analytics-writer/src/handlers/eservice-template/consumerServiceV2.ts index f65e736a9c..bb0e5f1d9e 100644 --- a/packages/domains-analytics-writer/src/handlers/eservice-template/consumerServiceV2.ts +++ b/packages/domains-analytics-writer/src/handlers/eservice-template/consumerServiceV2.ts @@ -53,7 +53,7 @@ export async function handleEserviceTemplateMessageV2( "EServiceTemplateVersionInterfaceDeleted", "EServiceTemplateVersionDocumentDeleted", "EServiceTemplateRiskAnalysisDeleted", - "EServiceTemplatePersonalDataUpdatedAfterPublish" + "EServiceTemplatePersonalDataFlagUpdatedAfterPublication" ), }, (msg) => { diff --git a/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts b/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts index bad0d195f3..34593417ec 100644 --- a/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts +++ b/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts @@ -345,7 +345,7 @@ export async function handleMessageV2({ { type: "EServiceTemplateVersionInterfaceUpdated" }, { type: "EServiceTemplateVersionPublished" }, { type: "EServiceTemplateVersionSuspended" }, - { type: "EServiceTemplatePersonalDataUpdatedAfterPublish" }, + { type: "EServiceTemplatePersonalDataFlagUpdatedAfterPublication" }, () => Promise.resolve ) .exhaustive(); diff --git a/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts b/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts index de717aca1b..710ce8e521 100644 --- a/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts +++ b/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts @@ -919,7 +919,7 @@ describe("eserviceTemplateUpdaterConsumerServiceV2", () => { "EServiceTemplateVersionInterfaceUpdated", "EServiceTemplateVersionPublished", "EServiceTemplateVersionSuspended", - "EServiceTemplatePersonalDataUpdatedAfterPublish", + "EServiceTemplatePersonalDataFlagUpdatedAfterPublication", ] as const)("Should ignore %s event", async (eventType) => { const decodedKafkaMessage: EServiceTemplateEventEnvelope = { sequence_num: 1, diff --git a/packages/eservice-template-process/src/model/domain/toEvent.ts b/packages/eservice-template-process/src/model/domain/toEvent.ts index 32b766eb99..a3aa2c8c4e 100644 --- a/packages/eservice-template-process/src/model/domain/toEvent.ts +++ b/packages/eservice-template-process/src/model/domain/toEvent.ts @@ -471,19 +471,20 @@ export const toCreateEventEServiceTemplateVersionActivated = ( correlationId, }); -export const toCreateEventEServiceTemplatePersonalDataUpdatedAfterPublish = ( - version: number, - eserviceTemplate: EServiceTemplate, - correlationId: CorrelationId -): CreateEvent => ({ - streamId: eserviceTemplate.id, - version, - event: { - type: "EServiceTemplatePersonalDataUpdatedAfterPublish", - event_version: 2, - data: { - eserviceTemplate: toEServiceTemplateV2(eserviceTemplate), +export const toCreateEventEServiceTemplatePersonalDataFlagUpdatedAfterPublication = + ( + version: number, + eserviceTemplate: EServiceTemplate, + correlationId: CorrelationId + ): CreateEvent => ({ + streamId: eserviceTemplate.id, + version, + event: { + type: "EServiceTemplatePersonalDataFlagUpdatedAfterPublication", + event_version: 2, + data: { + eserviceTemplate: toEServiceTemplateV2(eserviceTemplate), + }, }, - }, - correlationId, -}); + correlationId, + }); diff --git a/packages/eservice-template-process/src/services/eserviceTemplateService.ts b/packages/eservice-template-process/src/services/eserviceTemplateService.ts index 743897ace3..102869b30b 100644 --- a/packages/eservice-template-process/src/services/eserviceTemplateService.ts +++ b/packages/eservice-template-process/src/services/eserviceTemplateService.ts @@ -88,7 +88,7 @@ import { toCreateEventEServiceTemplateVersionDocumentUpdated, toCreateEventEServiceTemplateVersionDocumentDeleted, toCreateEventEServiceTemplateVersionInterfaceDeleted, - toCreateEventEServiceTemplatePersonalDataUpdatedAfterPublish, + toCreateEventEServiceTemplatePersonalDataFlagUpdatedAfterPublication, } from "../model/domain/toEvent.js"; import { config } from "../config/config.js"; import { @@ -1825,7 +1825,7 @@ export function eserviceTemplateServiceBuilder( }; const event = - toCreateEventEServiceTemplatePersonalDataUpdatedAfterPublish( + toCreateEventEServiceTemplatePersonalDataFlagUpdatedAfterPublication( eserviceTemplate.metadata.version, updatedEServiceTemplate, correlationId diff --git a/packages/eservice-template-readmodel-writer-sql/src/consumerServiceV2.ts b/packages/eservice-template-readmodel-writer-sql/src/consumerServiceV2.ts index 467abaff60..8d72868732 100644 --- a/packages/eservice-template-readmodel-writer-sql/src/consumerServiceV2.ts +++ b/packages/eservice-template-readmodel-writer-sql/src/consumerServiceV2.ts @@ -49,7 +49,7 @@ export async function handleMessageV2( { type: "EServiceTemplateVersionInterfaceUpdated" }, { type: "EServiceTemplateVersionPublished" }, { type: "EServiceTemplateVersionQuotasUpdated" }, - { type: "EServiceTemplatePersonalDataUpdatedAfterPublish" }, + { type: "EServiceTemplatePersonalDataFlagUpdatedAfterPublication" }, async (message) => { await eserviceTemplateWriterService.upsertEServiceTemplate( fromEServiceTemplateV2(eserviceTemplate), diff --git a/packages/eservice-template-readmodel-writer-sql/test/eserviceTemplateReadmodelWriter.integration.test.ts b/packages/eservice-template-readmodel-writer-sql/test/eserviceTemplateReadmodelWriter.integration.test.ts index a5195bf193..0df314b3d5 100644 --- a/packages/eservice-template-readmodel-writer-sql/test/eserviceTemplateReadmodelWriter.integration.test.ts +++ b/packages/eservice-template-readmodel-writer-sql/test/eserviceTemplateReadmodelWriter.integration.test.ts @@ -934,7 +934,7 @@ describe("database test", async () => { expect(retrievedEservice?.metadata).toStrictEqual({ version: 2 }); }); - it("EServiceTemplatePersonalDataUpdatedAfterPublish", async () => { + it("EServiceTemplatePersonalDataFlagUpdatedAfterPublication", async () => { const publishedVersion: EServiceTemplateVersion = { ...getMockEServiceTemplateVersion(), interface: getMockDocument(), @@ -960,7 +960,7 @@ describe("database test", async () => { sequence_num: 1, stream_id: mockEServiceTemplate.id, version: 2, - type: "EServiceTemplatePersonalDataUpdatedAfterPublish", + type: "EServiceTemplatePersonalDataFlagUpdatedAfterPublication", event_version: 2, data: payload, log_date: new Date(), diff --git a/packages/models/proto/v2/eservice-template/events.proto b/packages/models/proto/v2/eservice-template/events.proto index ea4730d469..34448dab38 100644 --- a/packages/models/proto/v2/eservice-template/events.proto +++ b/packages/models/proto/v2/eservice-template/events.proto @@ -121,6 +121,6 @@ message EServiceTemplateVersionActivatedV2 { EServiceTemplateV2 eserviceTemplate = 2; } -message EServiceTemplatePersonalDataUpdatedAfterPublishV2 { +message EServiceTemplatePersonalDataFlagUpdatedAfterPublicationV2 { EServiceTemplateV2 eserviceTemplate = 1; } From 7c879ec3f3512d302cc4c79bd926f6071b6b0998 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 25 Sep 2025 15:37:08 +0200 Subject: [PATCH 098/180] Rename event --- .../src/converters/toOutboundEventV2.ts | 2 +- ...ceTemplatePersonalDataUpdatedAfterPublish.test.ts | 6 +++--- .../src/handlers/handleEServiceTemplateEvent.ts | 2 +- .../src/eservice-template/eserviceTemplateEvents.ts | 12 +++++++----- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/packages/eservice-template-outbound-writer/src/converters/toOutboundEventV2.ts b/packages/eservice-template-outbound-writer/src/converters/toOutboundEventV2.ts index 3cb745043c..383d34f69c 100644 --- a/packages/eservice-template-outbound-writer/src/converters/toOutboundEventV2.ts +++ b/packages/eservice-template-outbound-writer/src/converters/toOutboundEventV2.ts @@ -55,7 +55,7 @@ export function toOutboundEventV2( { type: "EServiceTemplateDeleted" }, { type: "EServiceTemplateIntendedTargetUpdated" }, { type: "EServiceTemplateDescriptionUpdated" }, - { type: "EServiceTemplatePersonalDataUpdatedAfterPublish" }, + { type: "EServiceTemplatePersonalDataFlagUpdatedAfterPublication" }, (msg) => ({ event_version: msg.event_version, type: msg.type, diff --git a/packages/eservice-template-process/test/integration/updateEServiceTemplatePersonalDataUpdatedAfterPublish.test.ts b/packages/eservice-template-process/test/integration/updateEServiceTemplatePersonalDataUpdatedAfterPublish.test.ts index df7889cf6b..9df6f762e8 100644 --- a/packages/eservice-template-process/test/integration/updateEServiceTemplatePersonalDataUpdatedAfterPublish.test.ts +++ b/packages/eservice-template-process/test/integration/updateEServiceTemplatePersonalDataUpdatedAfterPublish.test.ts @@ -10,7 +10,7 @@ import { import { EServiceTemplate, toEServiceTemplateV2, - EServiceTemplatePersonalDataUpdatedAfterPublishV2, + EServiceTemplatePersonalDataFlagUpdatedAfterPublicationV2, operationForbidden, eserviceTemplateVersionState, EServiceTemplateVersion, @@ -63,12 +63,12 @@ describe("update EService Template personalData flag for an already created ESer expect(writtenEvent).toMatchObject({ stream_id: eserviceTemplate.id, version: "1", - type: "EServiceTemplatePersonalDataUpdatedAfterPublish", + type: "EServiceTemplatePersonalDataFlagUpdatedAfterPublication", event_version: 2, }); const writtenPayload = decodeProtobufPayload({ - messageType: EServiceTemplatePersonalDataUpdatedAfterPublishV2, + messageType: EServiceTemplatePersonalDataFlagUpdatedAfterPublicationV2, payload: writtenEvent.data, }); diff --git a/packages/m2m-event-dispatcher/src/handlers/handleEServiceTemplateEvent.ts b/packages/m2m-event-dispatcher/src/handlers/handleEServiceTemplateEvent.ts index 4f81436823..2e14977f47 100644 --- a/packages/m2m-event-dispatcher/src/handlers/handleEServiceTemplateEvent.ts +++ b/packages/m2m-event-dispatcher/src/handlers/handleEServiceTemplateEvent.ts @@ -38,7 +38,7 @@ export async function handleEServiceTemplateEvent( "EServiceTemplateVersionInterfaceUpdated", "EServiceTemplateVersionPublished", "EServiceTemplateVersionQuotasUpdated", - "EServiceTemplatePersonalDataUpdatedAfterPublish" + "EServiceTemplatePersonalDataFlagUpdatedAfterPublication" ), }, () => Promise.resolve(void 0) diff --git a/packages/models/src/eservice-template/eserviceTemplateEvents.ts b/packages/models/src/eservice-template/eserviceTemplateEvents.ts index 85cf6ea3d3..035513d073 100644 --- a/packages/models/src/eservice-template/eserviceTemplateEvents.ts +++ b/packages/models/src/eservice-template/eserviceTemplateEvents.ts @@ -25,7 +25,7 @@ import { EServiceTemplateVersionInterfaceUpdatedV2, EServiceTemplateVersionPublishedV2, EServiceTemplateVersionQuotasUpdatedV2, - EServiceTemplatePersonalDataUpdatedAfterPublishV2, + EServiceTemplatePersonalDataFlagUpdatedAfterPublicationV2, } from "../gen/v2/eservice-template/events.js"; import { protobufDecoder } from "../protobuf/protobuf.js"; import { EventEnvelope } from "../events/events.js"; @@ -148,8 +148,10 @@ export const EServiceTemplateEventV2 = z.discriminatedUnion("type", [ }), z.object({ event_version: z.literal(2), - type: z.literal("EServiceTemplatePersonalDataUpdatedAfterPublish"), - data: protobufDecoder(EServiceTemplatePersonalDataUpdatedAfterPublishV2), + type: z.literal("EServiceTemplatePersonalDataFlagUpdatedAfterPublication"), + data: protobufDecoder( + EServiceTemplatePersonalDataFlagUpdatedAfterPublicationV2 + ), }), ]); @@ -229,9 +231,9 @@ export function eserviceTemplateEventToBinaryDataV2( EServiceTemplateVersionQuotasUpdatedV2.toBinary(data) ) .with( - { type: "EServiceTemplatePersonalDataUpdatedAfterPublish" }, + { type: "EServiceTemplatePersonalDataFlagUpdatedAfterPublication" }, ({ data }) => - EServiceTemplatePersonalDataUpdatedAfterPublishV2.toBinary(data) + EServiceTemplatePersonalDataFlagUpdatedAfterPublicationV2.toBinary(data) ) .exhaustive(); } From 39aac138f8cf77f608fbfdf1628a8c5b6019d3f3 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 25 Sep 2025 15:45:30 +0200 Subject: [PATCH 099/180] Renaming --- .../src/converters/toOutboundEventV2.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eservice-template-outbound-writer/src/converters/toOutboundEventV2.ts b/packages/eservice-template-outbound-writer/src/converters/toOutboundEventV2.ts index 3cb745043c..383d34f69c 100644 --- a/packages/eservice-template-outbound-writer/src/converters/toOutboundEventV2.ts +++ b/packages/eservice-template-outbound-writer/src/converters/toOutboundEventV2.ts @@ -55,7 +55,7 @@ export function toOutboundEventV2( { type: "EServiceTemplateDeleted" }, { type: "EServiceTemplateIntendedTargetUpdated" }, { type: "EServiceTemplateDescriptionUpdated" }, - { type: "EServiceTemplatePersonalDataUpdatedAfterPublish" }, + { type: "EServiceTemplatePersonalDataFlagUpdatedAfterPublication" }, (msg) => ({ event_version: msg.event_version, type: msg.type, From 640060b5df1d8dcaaaf1ffe5e724a897f5c1cc02 Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Thu, 25 Sep 2025 15:49:02 +0200 Subject: [PATCH 100/180] test(m2m-gateway): update integration and api tests to handle personalData in EServiceTemplate --- packages/commons-test/src/apiMocks.ts | 1 + packages/m2m-gateway/src/api/eserviceTemplateApiConverter.ts | 1 + .../integration/eServiceTemplates/getEServiceTemplate.test.ts | 1 + 3 files changed, 3 insertions(+) diff --git a/packages/commons-test/src/apiMocks.ts b/packages/commons-test/src/apiMocks.ts index f7e922550d..12a3c73fcf 100644 --- a/packages/commons-test/src/apiMocks.ts +++ b/packages/commons-test/src/apiMocks.ts @@ -355,6 +355,7 @@ export function getMockedApiEServiceTemplate({ tenantKind: generateMock(eserviceTemplateApi.TenantKind), }, ], + personalData: generateMock(z.boolean().optional()), }; } diff --git a/packages/m2m-gateway/src/api/eserviceTemplateApiConverter.ts b/packages/m2m-gateway/src/api/eserviceTemplateApiConverter.ts index e5c7d9b55c..2610517e25 100644 --- a/packages/m2m-gateway/src/api/eserviceTemplateApiConverter.ts +++ b/packages/m2m-gateway/src/api/eserviceTemplateApiConverter.ts @@ -12,6 +12,7 @@ export function toM2MGatewayEServiceTemplate( name: template.name, technology: template.technology, isSignalHubEnabled: template.isSignalHubEnabled, + personalData: template.personalData, }; } diff --git a/packages/m2m-gateway/test/integration/eServiceTemplates/getEServiceTemplate.test.ts b/packages/m2m-gateway/test/integration/eServiceTemplates/getEServiceTemplate.test.ts index 87d75addcb..802456e9a5 100644 --- a/packages/m2m-gateway/test/integration/eServiceTemplates/getEServiceTemplate.test.ts +++ b/packages/m2m-gateway/test/integration/eServiceTemplates/getEServiceTemplate.test.ts @@ -36,6 +36,7 @@ describe("getEserviceTemplate", () => { name: mockApiTemplate.data.name, technology: mockApiTemplate.data.technology, isSignalHubEnabled: mockApiTemplate.data.isSignalHubEnabled, + personalData: mockApiTemplate.data.personalData, }; const result = await eserviceTemplateService.getEServiceTemplateById( From 0f1ec23209ba80f9f4ea2a39d3dd2b75cf0d5f7a Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 25 Sep 2025 15:54:10 +0200 Subject: [PATCH 101/180] Renaming --- packages/catalog-process/src/model/domain/toEvent.ts | 2 +- .../src/handlers/catalog/consumerServiceV2.ts | 2 +- packages/models/src/eservice/eserviceEvents.ts | 8 +++++--- packages/notification-email-sender/src/index.ts | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/catalog-process/src/model/domain/toEvent.ts b/packages/catalog-process/src/model/domain/toEvent.ts index d4c824e423..3f18049298 100644 --- a/packages/catalog-process/src/model/domain/toEvent.ts +++ b/packages/catalog-process/src/model/domain/toEvent.ts @@ -710,7 +710,7 @@ export const toCreateEventEServicePersonalDataFlagUpdatedByTemplateUpdate = ( streamId: eservice.id, version, event: { - type: "EServicePersonalDataUpdatedByTemplateUpdate", + type: "EServicePersonalDataFlagUpdatedByTemplateUpdate", event_version: 2, data: { eservice: toEServiceV2(eservice), diff --git a/packages/domains-analytics-writer/src/handlers/catalog/consumerServiceV2.ts b/packages/domains-analytics-writer/src/handlers/catalog/consumerServiceV2.ts index 102ebc600a..ee7d011458 100644 --- a/packages/domains-analytics-writer/src/handlers/catalog/consumerServiceV2.ts +++ b/packages/domains-analytics-writer/src/handlers/catalog/consumerServiceV2.ts @@ -79,7 +79,7 @@ export async function handleCatalogMessageV2( "EServiceSignalHubEnabled", "EServiceSignalHubDisabled", "EServicePersonalDataFlagUpdatedAfterPublication" - "EServicePersonalDataUpdatedByTemplateUpdate" + "EServicePersonalDataFlagUpdatedByTemplateUpdate" ), }, (msg) => { diff --git a/packages/models/src/eservice/eserviceEvents.ts b/packages/models/src/eservice/eserviceEvents.ts index c00d211b2d..2ccc8cca09 100644 --- a/packages/models/src/eservice/eserviceEvents.ts +++ b/packages/models/src/eservice/eserviceEvents.ts @@ -260,8 +260,10 @@ export function catalogEventToBinaryDataV2(event: EServiceEventV2): Uint8Array { ({ data }) => EServicePersonalDataFlagUpdatedAfterPublicationV2.toBinary(data) ) - .with({ type: "EServicePersonalDataUpdatedByTemplateUpdate" }, ({ data }) => - EServicePersonalDataFlagUpdatedByTemplateUpdateV2.toBinary(data) + .with( + { type: "EServicePersonalDataFlagUpdatedByTemplateUpdate" }, + ({ data }) => + EServicePersonalDataFlagUpdatedByTemplateUpdateV2.toBinary(data) ) .exhaustive(); } @@ -555,7 +557,7 @@ export const EServiceEventV2 = z.discriminatedUnion("type", [ }), z.object({ event_version: z.literal(2), - type: z.literal("EServicePersonalDataUpdatedByTemplateUpdate"), + type: z.literal("EServicePersonalDataFlagUpdatedByTemplateUpdate"), data: protobufDecoder(EServicePersonalDataFlagUpdatedByTemplateUpdateV2), }), ]); diff --git a/packages/notification-email-sender/src/index.ts b/packages/notification-email-sender/src/index.ts index ceea4fc706..d1988d58f4 100644 --- a/packages/notification-email-sender/src/index.ts +++ b/packages/notification-email-sender/src/index.ts @@ -163,7 +163,7 @@ export async function handleCatalogMessage( "EServiceSignalHubEnabled", "EServiceSignalHubDisabled", "EServicePersonalDataFlagUpdatedAfterPublication", - "EServicePersonalDataUpdatedByTemplateUpdate" + "EServicePersonalDataFlagUpdatedByTemplateUpdate" ), }, () => { From 73be09b3b69a158802c59c0c33b8ac852b53c272 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 25 Sep 2025 15:57:02 +0200 Subject: [PATCH 102/180] Fix --- .../m2m-event-dispatcher/src/handlers/handleEServiceEvent.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/m2m-event-dispatcher/src/handlers/handleEServiceEvent.ts b/packages/m2m-event-dispatcher/src/handlers/handleEServiceEvent.ts index f25234684d..437496b34b 100644 --- a/packages/m2m-event-dispatcher/src/handlers/handleEServiceEvent.ts +++ b/packages/m2m-event-dispatcher/src/handlers/handleEServiceEvent.ts @@ -56,7 +56,7 @@ export async function handleEServiceEvent( "EServiceDescriptorDocumentUpdatedByTemplateUpdate", "EServiceSignalHubEnabled", "EServiceSignalHubDisabled", - "EServicePersonalDataFlagUpdatedAfterPublication" + "EServicePersonalDataFlagUpdatedAfterPublication", "EServicePersonalDataFlagUpdatedByTemplateUpdate" ), }, From 366fe6a182d21ad783eccedce8a6d1e82ec3fed8 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 25 Sep 2025 15:59:38 +0200 Subject: [PATCH 103/180] Fix --- .../src/handlers/eservices/handleEserviceEvent.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/in-app-notification-dispatcher/src/handlers/eservices/handleEserviceEvent.ts b/packages/in-app-notification-dispatcher/src/handlers/eservices/handleEserviceEvent.ts index 907ec6fdcc..65129d51ad 100644 --- a/packages/in-app-notification-dispatcher/src/handlers/eservices/handleEserviceEvent.ts +++ b/packages/in-app-notification-dispatcher/src/handlers/eservices/handleEserviceEvent.ts @@ -92,7 +92,7 @@ export async function handleEServiceEvent( "EServiceIsClientAccessDelegableDisabled", "EServiceSignalHubEnabled", "EServiceSignalHubDisabled", - "EServicePersonalDataFlagUpdatedAfterPublication" + "EServicePersonalDataFlagUpdatedAfterPublication", "EServicePersonalDataFlagUpdatedByTemplateUpdate" ), }, From 76db62788615a5aef3ad045a5edb3615be33389a Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 25 Sep 2025 16:05:27 +0200 Subject: [PATCH 104/180] Fix --- .../src/handlers/catalog/consumerServiceV2.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/domains-analytics-writer/src/handlers/catalog/consumerServiceV2.ts b/packages/domains-analytics-writer/src/handlers/catalog/consumerServiceV2.ts index ee7d011458..c2881329b2 100644 --- a/packages/domains-analytics-writer/src/handlers/catalog/consumerServiceV2.ts +++ b/packages/domains-analytics-writer/src/handlers/catalog/consumerServiceV2.ts @@ -78,7 +78,7 @@ export async function handleCatalogMessageV2( "EServiceDraftDescriptorDeleted", "EServiceSignalHubEnabled", "EServiceSignalHubDisabled", - "EServicePersonalDataFlagUpdatedAfterPublication" + "EServicePersonalDataFlagUpdatedAfterPublication", "EServicePersonalDataFlagUpdatedByTemplateUpdate" ), }, From 89f129e062353d6512ff5623047aea740676c237 Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Thu, 25 Sep 2025 16:06:09 +0200 Subject: [PATCH 105/180] feat(m2m-gateway): add personalData field in toM2MGatewayApiEService apiConverter --- packages/m2m-gateway/src/api/eserviceApiConverter.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/m2m-gateway/src/api/eserviceApiConverter.ts b/packages/m2m-gateway/src/api/eserviceApiConverter.ts index 80c686e08d..fcd65d20d9 100644 --- a/packages/m2m-gateway/src/api/eserviceApiConverter.ts +++ b/packages/m2m-gateway/src/api/eserviceApiConverter.ts @@ -36,6 +36,7 @@ export function toM2MGatewayApiEService( isConsumerDelegable: eservice.isConsumerDelegable, isClientAccessDelegable: eservice.isClientAccessDelegable, templateId: eservice.templateId, + personalData: eservice.personalData, }; } From fb6617a54fbff30dd0f8b4423234a2c274865ab3 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 25 Sep 2025 16:16:28 +0200 Subject: [PATCH 106/180] Renaming --- ...serviceTemplateInstancesUpdaterConsumerServiceV2.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts b/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts index 7d97832d1e..34c08b0821 100644 --- a/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts +++ b/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts @@ -20,7 +20,7 @@ import { EServiceTemplateDescriptionUpdatedV2, EServiceTemplateEventEnvelope, EServiceTemplateNameUpdatedV2, - EServiceTemplatePersonalDataUpdatedAfterPublishV2, + EServiceTemplatePersonalDataFlagUpdatedAfterPublicationV2, EServiceTemplateVersion, EServiceTemplateVersionAttributesUpdatedV2, EServiceTemplateVersionDocumentAddedV2, @@ -910,7 +910,7 @@ describe("eserviceTemplateUpdaterConsumerServiceV2", () => { ...eserviceTemplate, personalData: true, }; - const payload: EServiceTemplatePersonalDataUpdatedAfterPublishV2 = { + const payload: EServiceTemplatePersonalDataFlagUpdatedAfterPublicationV2 = { eserviceTemplate: toEServiceTemplateV2(mockTemplate), }; @@ -918,7 +918,7 @@ describe("eserviceTemplateUpdaterConsumerServiceV2", () => { sequence_num: 1, stream_id: eserviceTemplate.id, version: 2, - type: "EServiceTemplatePersonalDataUpdatedAfterPublish", + type: "EServiceTemplatePersonalDataFlagUpdatedAfterPublication", event_version: 2, data: payload, log_date: new Date(), From b4c0bce4e8920a68aba1772a5d3a591a136e764d Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 25 Sep 2025 16:24:18 +0200 Subject: [PATCH 107/180] Rename error --- .../eservice-template-process/src/model/domain/errors.ts | 8 ++++---- .../src/services/eserviceTemplateService.ts | 4 ++-- .../src/utilities/errorMappers.ts | 2 +- .../test/api/publishEServiceTemplateVersion.test.ts | 4 ++-- .../integration/publishEServiceTemplateVersion.test.ts | 9 +++------ 5 files changed, 12 insertions(+), 15 deletions(-) diff --git a/packages/eservice-template-process/src/model/domain/errors.ts b/packages/eservice-template-process/src/model/domain/errors.ts index c7c65c747f..95a994cbf7 100644 --- a/packages/eservice-template-process/src/model/domain/errors.ts +++ b/packages/eservice-template-process/src/model/domain/errors.ts @@ -34,7 +34,7 @@ export const errorCodes = { eserviceTemplateDocumentNotFound: "0025", riskAnalysisNotFound: "0026", attributeDuplicatedInGroup: "0027", - eserviceTemplatePersonalDataMustBeSet: "0028", + missingPersonalDataFlag: "0028", }; export type ErrorCodes = keyof typeof errorCodes; @@ -300,13 +300,13 @@ export function attributeDuplicatedInGroup( }); } -export function eserviceTemplatePersonalDataMustBeSet( +export function missingPersonalDataFlag( eserviceTemplateId: EServiceTemplateId, eserviceTemplateVersionId: EServiceTemplateVersionId ): ApiError { return new ApiError({ detail: `Template version ${eserviceTemplateVersionId} in eserviceTemplate ${eserviceTemplateId} can't be published because personalData flag must be set`, - code: "eserviceTemplatePersonalDataMustBeSet", - title: "EService Template personalData must be set before publication", + code: "missingPersonalDataFlag", + title: "EService Template personalData flag must be set before publication", }); } diff --git a/packages/eservice-template-process/src/services/eserviceTemplateService.ts b/packages/eservice-template-process/src/services/eserviceTemplateService.ts index c0132436f7..dcdd2dd8a1 100644 --- a/packages/eservice-template-process/src/services/eserviceTemplateService.ts +++ b/packages/eservice-template-process/src/services/eserviceTemplateService.ts @@ -49,7 +49,7 @@ import { instanceNameConflict, notValidEServiceTemplateVersionState, attributeDuplicatedInGroup, - eserviceTemplatePersonalDataMustBeSet, + missingPersonalDataFlag, } from "../model/domain/errors.js"; import { versionAttributeGroupSupersetMissingInAttributesSeed, @@ -531,7 +531,7 @@ export function eserviceTemplateServiceBuilder( config.featureFlagEservicePersonalData && eserviceTemplate.data.personalData === undefined ) { - throw eserviceTemplatePersonalDataMustBeSet( + throw missingPersonalDataFlag( eserviceTemplateId, eserviceTemplateVersionId ); diff --git a/packages/eservice-template-process/src/utilities/errorMappers.ts b/packages/eservice-template-process/src/utilities/errorMappers.ts index 744ba2fb4e..a006e222cb 100644 --- a/packages/eservice-template-process/src/utilities/errorMappers.ts +++ b/packages/eservice-template-process/src/utilities/errorMappers.ts @@ -60,7 +60,7 @@ export const publishEServiceTemplateVersionErrorMapper = ( .with( "notValidEServiceTemplateVersionState", "riskAnalysisValidationFailed", - "eserviceTemplatePersonalDataMustBeSet", + "missingPersonalDataFlag", () => HTTP_STATUS_BAD_REQUEST ) .with("operationForbidden", () => HTTP_STATUS_FORBIDDEN) diff --git a/packages/eservice-template-process/test/api/publishEServiceTemplateVersion.test.ts b/packages/eservice-template-process/test/api/publishEServiceTemplateVersion.test.ts index b75b21301e..946dd53734 100644 --- a/packages/eservice-template-process/test/api/publishEServiceTemplateVersion.test.ts +++ b/packages/eservice-template-process/test/api/publishEServiceTemplateVersion.test.ts @@ -20,7 +20,7 @@ import request from "supertest"; import { api, eserviceTemplateService } from "../vitest.api.setup.js"; import { eserviceTemplateNotFound, - eserviceTemplatePersonalDataMustBeSet, + missingPersonalDataFlag, eserviceTemplateVersionNotFound, missingTemplateVersionInterface, notValidEServiceTemplateVersionState, @@ -100,7 +100,7 @@ describe("API POST /templates/:templateId/versions/:templateVersionId/publish", expectedStatus: 400, }, { - error: eserviceTemplatePersonalDataMustBeSet( + error: missingPersonalDataFlag( mockEserviceTemplate.id, mockEserviceTemplate.versions[0].id ), diff --git a/packages/eservice-template-process/test/integration/publishEServiceTemplateVersion.test.ts b/packages/eservice-template-process/test/integration/publishEServiceTemplateVersion.test.ts index 1134f4a4b1..807edb451e 100644 --- a/packages/eservice-template-process/test/integration/publishEServiceTemplateVersion.test.ts +++ b/packages/eservice-template-process/test/integration/publishEServiceTemplateVersion.test.ts @@ -28,7 +28,7 @@ import { import { expect, describe, it, afterAll, vi, beforeAll } from "vitest"; import { eserviceTemplateNotFound, - eserviceTemplatePersonalDataMustBeSet, + missingPersonalDataFlag, eserviceTemplateVersionNotFound, missingRiskAnalysis, missingTemplateVersionInterface, @@ -425,7 +425,7 @@ describe("publishEServiceTemplateVersion", () => { ).equal(undefined); }); - it("should throw eserviceTemplatePersonalDataMustBeSet if the template has personalData undefined", async () => { + it("should throw missingPersonalDataFlag if the template has personalData undefined", async () => { const eserviceTemplateVersion: EServiceTemplateVersion = { ...getMockEServiceTemplateVersion(), state: descriptorState.draft, @@ -449,10 +449,7 @@ describe("publishEServiceTemplateVersion", () => { }) ) ).rejects.toThrowError( - eserviceTemplatePersonalDataMustBeSet( - eserviceTemplate.id, - eserviceTemplateVersion.id - ) + missingPersonalDataFlag(eserviceTemplate.id, eserviceTemplateVersion.id) ); }); }); From 87de2856a615e7dfd2a472d7ee02ef1dcf3fa7a1 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 25 Sep 2025 16:30:50 +0200 Subject: [PATCH 108/180] Renaming --- packages/api-clients/open-api/bffApi.yml | 4 ++-- packages/api-clients/open-api/catalogApi.yml | 4 ++-- .../src/services/catalogService.ts | 2 +- .../updateEServicePersonalData.test.ts | 14 +++++++------- packages/backend-for-frontend/test/mockUtils.ts | 4 ++-- .../test/api/updateEServicePersonalData.test.ts | 6 +++--- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/packages/api-clients/open-api/bffApi.yml b/packages/api-clients/open-api/bffApi.yml index ff44590089..2ea56b6faa 100644 --- a/packages/api-clients/open-api/bffApi.yml +++ b/packages/api-clients/open-api/bffApi.yml @@ -5960,7 +5960,7 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/EServicePersonalDataUpdateSeed" + $ref: "#/components/schemas/EServicePersonalDataFlagUpdateSeed" responses: "204": description: EService personalData flag updated @@ -21885,7 +21885,7 @@ components: type: boolean required: - isSignalHubEnabled - EServicePersonalDataUpdateSeed: + EServicePersonalDataFlagUpdateSeed: type: object additionalProperties: false properties: diff --git a/packages/api-clients/open-api/catalogApi.yml b/packages/api-clients/open-api/catalogApi.yml index e72377a0a0..aba8f08bc2 100644 --- a/packages/api-clients/open-api/catalogApi.yml +++ b/packages/api-clients/open-api/catalogApi.yml @@ -1992,7 +1992,7 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/EServicePersonalDataUpdateSeed" + $ref: "#/components/schemas/EServicePersonalDataFlagUpdateSeed" responses: "200": description: EService personalData flag updated @@ -3478,7 +3478,7 @@ components: type: boolean required: - isSignalHubEnabled - EServicePersonalDataUpdateSeed: + EServicePersonalDataFlagUpdateSeed: type: object additionalProperties: false properties: diff --git a/packages/backend-for-frontend/src/services/catalogService.ts b/packages/backend-for-frontend/src/services/catalogService.ts index fdb1e647d6..2280c64e2f 100644 --- a/packages/backend-for-frontend/src/services/catalogService.ts +++ b/packages/backend-for-frontend/src/services/catalogService.ts @@ -601,7 +601,7 @@ export function catalogServiceBuilder( updateEServicePersonalDataFlag: async ( { headers, logger }: WithLogger, eServiceId: EServiceId, - personalDataSeed: bffApi.EServicePersonalDataUpdateSeed + personalDataSeed: bffApi.EServicePersonalDataFlagUpdateSeed ): Promise => { logger.info( `Set personal flag for E-Service with id = ${eServiceId} to ${personalDataSeed.personalData}` diff --git a/packages/backend-for-frontend/test/api/catalogRouter/updateEServicePersonalData.test.ts b/packages/backend-for-frontend/test/api/catalogRouter/updateEServicePersonalData.test.ts index 9def68c3df..edc852bdaf 100644 --- a/packages/backend-for-frontend/test/api/catalogRouter/updateEServicePersonalData.test.ts +++ b/packages/backend-for-frontend/test/api/catalogRouter/updateEServicePersonalData.test.ts @@ -7,20 +7,20 @@ import { authRole } from "pagopa-interop-commons"; import { bffApi } from "pagopa-interop-api-clients"; import { api, clients } from "../../vitest.api.setup.js"; import { - getMockBffApiEServicePersonalDataUpdateSeed, + getMockBffApiEServicePersonalDataFlagUpdateSeed, getMockBffApiEServicePersonaData, } from "../../mockUtils.js"; import { appBasePath } from "../../../src/config/appBasePath.js"; describe("API POST /eservices/:eServiceId/personalData", () => { - const mockEServicePersonalDataUpdateSeed = - getMockBffApiEServicePersonalDataUpdateSeed(); + const mockEServicePersonalDataFlagUpdateSeed = + getMockBffApiEServicePersonalDataFlagUpdateSeed(); const mockEService = getMockBffApiEServicePersonaData(); const makeRequest = async ( token: string, eServiceId: EServiceId = mockEService.id, - body: bffApi.EServicePersonalDataUpdateSeed = mockEServicePersonalDataUpdateSeed + body: bffApi.EServicePersonalDataFlagUpdateSeed = mockEServicePersonalDataFlagUpdateSeed ) => request(api) .post(`${appBasePath}/eservices/${eServiceId}/personalData`) @@ -44,13 +44,13 @@ describe("API POST /eservices/:eServiceId/personalData", () => { { body: {} }, { body: { - ...mockEServicePersonalDataUpdateSeed, + ...mockEServicePersonalDataFlagUpdateSeed, extraField: 1, }, }, { body: { - ...mockEServicePersonalDataUpdateSeed, + ...mockEServicePersonalDataFlagUpdateSeed, personalData: "invalid", }, }, @@ -61,7 +61,7 @@ describe("API POST /eservices/:eServiceId/personalData", () => { const res = await makeRequest( token, eServiceId, - body as bffApi.EServicePersonalDataUpdateSeed + body as bffApi.EServicePersonalDataFlagUpdateSeed ); expect(res.status).toBe(400); } diff --git a/packages/backend-for-frontend/test/mockUtils.ts b/packages/backend-for-frontend/test/mockUtils.ts index 13ad0b141c..8b1936c71c 100644 --- a/packages/backend-for-frontend/test/mockUtils.ts +++ b/packages/backend-for-frontend/test/mockUtils.ts @@ -368,8 +368,8 @@ export const getMockBffApiInstanceEServiceSeed = isConsumerDelegable: generateMock(z.boolean().optional()), }); -export const getMockBffApiEServicePersonalDataUpdateSeed = - (): bffApi.EServicePersonalDataUpdateSeed => ({ +export const getMockBffApiEServicePersonalDataFlagUpdateSeed = + (): bffApi.EServicePersonalDataFlagUpdateSeed => ({ personalData: generateMock(z.boolean()), }); diff --git a/packages/catalog-process/test/api/updateEServicePersonalData.test.ts b/packages/catalog-process/test/api/updateEServicePersonalData.test.ts index 8b09f17724..de43ff9bee 100644 --- a/packages/catalog-process/test/api/updateEServicePersonalData.test.ts +++ b/packages/catalog-process/test/api/updateEServicePersonalData.test.ts @@ -42,7 +42,7 @@ describe("API /eservices/{eServiceId}/personalData authorization test", () => { const personalData = randomArrayItem([false, true]); - const eserviceSeed: catalogApi.EServicePersonalDataUpdateSeed = { + const eserviceSeed: catalogApi.EServicePersonalDataFlagUpdateSeed = { personalData, }; @@ -53,7 +53,7 @@ describe("API /eservices/{eServiceId}/personalData authorization test", () => { const makeRequest = async ( token: string, eServiceId: EServiceId, - body: catalogApi.EServicePersonalDataUpdateSeed = eserviceSeed + body: catalogApi.EServicePersonalDataFlagUpdateSeed = eserviceSeed ) => request(api) .post(`/eservices/${eServiceId}/personalData`) @@ -120,7 +120,7 @@ describe("API /eservices/{eServiceId}/personalData authorization test", () => { const res = await makeRequest( token, eServiceId as EServiceId, - body as catalogApi.EServicePersonalDataUpdateSeed + body as catalogApi.EServicePersonalDataFlagUpdateSeed ); expect(res.status).toBe(400); From 852cae41d13488a8c92b256f6c9cb5e76c5a841d Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 25 Sep 2025 16:32:20 +0200 Subject: [PATCH 109/180] Update endpoint path --- packages/api-clients/open-api/bffApi.yml | 2 +- packages/api-clients/open-api/catalogApi.yml | 2 +- packages/backend-for-frontend/src/routers/catalogRouter.ts | 2 +- .../test/api/catalogRouter/updateEServicePersonalData.test.ts | 4 ++-- packages/catalog-process/src/routers/EServiceRouter.ts | 2 +- .../test/api/updateEServicePersonalData.test.ts | 4 ++-- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/api-clients/open-api/bffApi.yml b/packages/api-clients/open-api/bffApi.yml index 2ea56b6faa..5b4fec9bdc 100644 --- a/packages/api-clients/open-api/bffApi.yml +++ b/packages/api-clients/open-api/bffApi.yml @@ -5938,7 +5938,7 @@ paths: application/json: schema: $ref: "#/components/schemas/Problem" - /eservices/{eServiceId}/personalData: + /eservices/{eServiceId}/personalDataFlag: post: security: - bearerAuth: [] diff --git a/packages/api-clients/open-api/catalogApi.yml b/packages/api-clients/open-api/catalogApi.yml index aba8f08bc2..b2929e9d03 100644 --- a/packages/api-clients/open-api/catalogApi.yml +++ b/packages/api-clients/open-api/catalogApi.yml @@ -1968,7 +1968,7 @@ paths: application/json: schema: $ref: "#/components/schemas/Problem" - /eservices/{eServiceId}/personalData: + /eservices/{eServiceId}/personalDataFlag: parameters: - $ref: "#/components/parameters/CorrelationIdHeader" post: diff --git a/packages/backend-for-frontend/src/routers/catalogRouter.ts b/packages/backend-for-frontend/src/routers/catalogRouter.ts index 9cc8445a74..bf78c7d893 100644 --- a/packages/backend-for-frontend/src/routers/catalogRouter.ts +++ b/packages/backend-for-frontend/src/routers/catalogRouter.ts @@ -734,7 +734,7 @@ const catalogRouter = ( return res.status(errorRes.status).send(errorRes); } }) - .post("/eservices/:eServiceId/personalData", async (req, res) => { + .post("/eservices/:eServiceId/personalDataFlag", async (req, res) => { const ctx = fromBffAppContext(req.ctx, req.headers); try { await catalogService.updateEServicePersonalDataFlag( diff --git a/packages/backend-for-frontend/test/api/catalogRouter/updateEServicePersonalData.test.ts b/packages/backend-for-frontend/test/api/catalogRouter/updateEServicePersonalData.test.ts index edc852bdaf..59df11a655 100644 --- a/packages/backend-for-frontend/test/api/catalogRouter/updateEServicePersonalData.test.ts +++ b/packages/backend-for-frontend/test/api/catalogRouter/updateEServicePersonalData.test.ts @@ -12,7 +12,7 @@ import { } from "../../mockUtils.js"; import { appBasePath } from "../../../src/config/appBasePath.js"; -describe("API POST /eservices/:eServiceId/personalData", () => { +describe("API POST /eservices/:eServiceId/personalDataFlag", () => { const mockEServicePersonalDataFlagUpdateSeed = getMockBffApiEServicePersonalDataFlagUpdateSeed(); const mockEService = getMockBffApiEServicePersonaData(); @@ -23,7 +23,7 @@ describe("API POST /eservices/:eServiceId/personalData", () => { body: bffApi.EServicePersonalDataFlagUpdateSeed = mockEServicePersonalDataFlagUpdateSeed ) => request(api) - .post(`${appBasePath}/eservices/${eServiceId}/personalData`) + .post(`${appBasePath}/eservices/${eServiceId}/personalDataFlag`) .set("Authorization", `Bearer ${token}`) .set("X-Correlation-Id", generateId()) .send(body); diff --git a/packages/catalog-process/src/routers/EServiceRouter.ts b/packages/catalog-process/src/routers/EServiceRouter.ts index 1c7520091a..1dd62ec33b 100644 --- a/packages/catalog-process/src/routers/EServiceRouter.ts +++ b/packages/catalog-process/src/routers/EServiceRouter.ts @@ -1471,7 +1471,7 @@ const eservicesRouter = ( } } ) - .post("/eservices/:eServiceId/personalData", async (req, res) => { + .post("/eservices/:eServiceId/personalDataFlag", async (req, res) => { const ctx = fromAppContext(req.ctx); try { validateAuthorization(ctx, [ADMIN_ROLE, API_ROLE]); diff --git a/packages/catalog-process/test/api/updateEServicePersonalData.test.ts b/packages/catalog-process/test/api/updateEServicePersonalData.test.ts index de43ff9bee..a25de7c2fd 100644 --- a/packages/catalog-process/test/api/updateEServicePersonalData.test.ts +++ b/packages/catalog-process/test/api/updateEServicePersonalData.test.ts @@ -24,7 +24,7 @@ import { eserviceWithoutValidDescriptors, } from "../../src/model/domain/errors.js"; -describe("API /eservices/{eServiceId}/personalData authorization test", () => { +describe("API /eservices/{eServiceId}/personalDataFlag authorization test", () => { const descriptor: Descriptor = { ...getMockDescriptor(), state: descriptorState.published, @@ -56,7 +56,7 @@ describe("API /eservices/{eServiceId}/personalData authorization test", () => { body: catalogApi.EServicePersonalDataFlagUpdateSeed = eserviceSeed ) => request(api) - .post(`/eservices/${eServiceId}/personalData`) + .post(`/eservices/${eServiceId}/personalDataFlag`) .set("Authorization", `Bearer ${token}`) .set("X-Correlation-Id", generateId()) .send(body); From f4312a484aee9c603b0074fa37a239f68acc2877 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 25 Sep 2025 16:35:16 +0200 Subject: [PATCH 110/180] Renaming --- packages/api-clients/open-api/bffApi.yml | 6 +++--- .../api-clients/open-api/eserviceTemplateApi.yml | 6 +++--- .../src/services/eserviceTemplateService.ts | 2 +- .../updateEServiceTemplatePersonalData.test.ts | 12 ++++++------ packages/backend-for-frontend/test/mockUtils.ts | 4 ++-- .../api/updateEServiceTemplatePersonalData.test.ts | 6 +++--- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/packages/api-clients/open-api/bffApi.yml b/packages/api-clients/open-api/bffApi.yml index edceb30f96..791a5757e8 100644 --- a/packages/api-clients/open-api/bffApi.yml +++ b/packages/api-clients/open-api/bffApi.yml @@ -19968,7 +19968,7 @@ paths: application/problem+json: schema: $ref: "#/components/schemas/Problem" - /eservices/templates/{eServiceTemplateId}/personalData: + /eservices/templates/{eServiceTemplateId}/personalDataFlag: post: security: - bearerAuth: [] @@ -19990,7 +19990,7 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/EServiceTemplatePersonalDataUpdateSeed" + $ref: "#/components/schemas/EServiceTemplatePersonalDataFlagUpdateSeed" responses: "204": description: EService template personalData flag updated @@ -25177,7 +25177,7 @@ components: required: - id - explicitAttributeVerification - EServiceTemplatePersonalDataUpdateSeed: + EServiceTemplatePersonalDataFlagUpdateSeed: type: object additionalProperties: false properties: diff --git a/packages/api-clients/open-api/eserviceTemplateApi.yml b/packages/api-clients/open-api/eserviceTemplateApi.yml index 91d25685b7..bc03496c99 100644 --- a/packages/api-clients/open-api/eserviceTemplateApi.yml +++ b/packages/api-clients/open-api/eserviceTemplateApi.yml @@ -1170,7 +1170,7 @@ paths: application/problem+json: schema: $ref: "#/components/schemas/Problem" - /templates/{templateId}/personalData: + /templates/{templateId}/personalDataFlag: parameters: - $ref: "#/components/parameters/CorrelationIdHeader" post: @@ -1194,7 +1194,7 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/EServiceTemplatePersonalDataUpdateSeed" + $ref: "#/components/schemas/EServiceTemplatePersonalDataFlagUpdateSeed" responses: "200": description: EService template personalData flag updated @@ -1480,7 +1480,7 @@ components: type: string minLength: 5 maxLength: 60 - EServiceTemplatePersonalDataUpdateSeed: + EServiceTemplatePersonalDataFlagUpdateSeed: type: object additionalProperties: false properties: diff --git a/packages/backend-for-frontend/src/services/eserviceTemplateService.ts b/packages/backend-for-frontend/src/services/eserviceTemplateService.ts index 38fe3c2bc8..125a87c200 100644 --- a/packages/backend-for-frontend/src/services/eserviceTemplateService.ts +++ b/packages/backend-for-frontend/src/services/eserviceTemplateService.ts @@ -658,7 +658,7 @@ export function eserviceTemplateServiceBuilder( updateEServiceTemplatePersonalDataFlag: async ( { logger, headers }: WithLogger, templateId: EServiceTemplateId, - personalDataSeed: bffApi.EServiceTemplatePersonalDataUpdateSeed + personalDataSeed: bffApi.EServiceTemplatePersonalDataFlagUpdateSeed ): Promise => { logger.info( `Set personal flag for E-Service Template with id = ${templateId} to ${personalDataSeed.personalData}` diff --git a/packages/backend-for-frontend/test/api/eserviceTemplateRouter/updateEServiceTemplatePersonalData.test.ts b/packages/backend-for-frontend/test/api/eserviceTemplateRouter/updateEServiceTemplatePersonalData.test.ts index 9508c0acb6..e841931548 100644 --- a/packages/backend-for-frontend/test/api/eserviceTemplateRouter/updateEServiceTemplatePersonalData.test.ts +++ b/packages/backend-for-frontend/test/api/eserviceTemplateRouter/updateEServiceTemplatePersonalData.test.ts @@ -9,15 +9,15 @@ import { api, clients } from "../../vitest.api.setup.js"; import { appBasePath } from "../../../src/config/appBasePath.js"; import { getMockBffApiEServiceTemplatePersonaData, - getMockBffApiEServiceTemplatePersonalDataUpdateSeed, + getMockBffApiEServiceTemplatePersonalDataFlagUpdateSeed, } from "../../mockUtils.js"; describe("API POST /eservices/templates/:eServiceTemplateId/personalData", () => { const mockEServiceTemplate = { ...getMockBffApiEServiceTemplatePersonaData(), }; - const mockEServiceTemplatePersonalDataUpdateSeed = - getMockBffApiEServiceTemplatePersonalDataUpdateSeed(); + const mockEServiceTemplatePersonalDataFlagUpdateSeed = + getMockBffApiEServiceTemplatePersonalDataFlagUpdateSeed(); beforeEach(() => { clients.eserviceTemplateProcessClient.updateEServiceTemplatePersonalDataAfterPublish = @@ -27,7 +27,7 @@ describe("API POST /eservices/templates/:eServiceTemplateId/personalData", () => const makeRequest = async ( token: string, eServiceTemplateId: EServiceTemplateId = mockEServiceTemplate.id, - body: bffApi.EServiceTemplatePersonalDataUpdateSeed = mockEServiceTemplatePersonalDataUpdateSeed + body: bffApi.EServiceTemplatePersonalDataFlagUpdateSeed = mockEServiceTemplatePersonalDataFlagUpdateSeed ) => request(api) .post( @@ -48,7 +48,7 @@ describe("API POST /eservices/templates/:eServiceTemplateId/personalData", () => { body: {} }, { body: { - ...mockEServiceTemplatePersonalDataUpdateSeed, + ...mockEServiceTemplatePersonalDataFlagUpdateSeed, extraField: 1, }, }, @@ -64,7 +64,7 @@ describe("API POST /eservices/templates/:eServiceTemplateId/personalData", () => const res = await makeRequest( token, eServiceTemplateId, - body as bffApi.EServiceTemplatePersonalDataUpdateSeed + body as bffApi.EServiceTemplatePersonalDataFlagUpdateSeed ); expect(res.status).toBe(400); } diff --git a/packages/backend-for-frontend/test/mockUtils.ts b/packages/backend-for-frontend/test/mockUtils.ts index 3f6c820bc9..4470eb32ef 100644 --- a/packages/backend-for-frontend/test/mockUtils.ts +++ b/packages/backend-for-frontend/test/mockUtils.ts @@ -460,8 +460,8 @@ export const getMockBffApiEServiceNameUpdateSeed = name: generateMock(z.string()), }); -export const getMockBffApiEServiceTemplatePersonalDataUpdateSeed = - (): bffApi.EServiceTemplatePersonalDataUpdateSeed => ({ +export const getMockBffApiEServiceTemplatePersonalDataFlagUpdateSeed = + (): bffApi.EServiceTemplatePersonalDataFlagUpdateSeed => ({ personalData: generateMock(z.boolean()), }); diff --git a/packages/eservice-template-process/test/api/updateEServiceTemplatePersonalData.test.ts b/packages/eservice-template-process/test/api/updateEServiceTemplatePersonalData.test.ts index be3f9e8768..04b458aeb0 100644 --- a/packages/eservice-template-process/test/api/updateEServiceTemplatePersonalData.test.ts +++ b/packages/eservice-template-process/test/api/updateEServiceTemplatePersonalData.test.ts @@ -45,7 +45,7 @@ describe("API /templates/{templateId}/personalData", () => { const personalData = randomArrayItem([false, true]); - const eserviceTemplateSeed: eserviceTemplateApi.EServiceTemplatePersonalDataUpdateSeed = + const eserviceTemplateSeed: eserviceTemplateApi.EServiceTemplatePersonalDataFlagUpdateSeed = { personalData }; eserviceTemplateService.updateEServiceTemplatePersonalDataAfterPublish = vi @@ -55,7 +55,7 @@ describe("API /templates/{templateId}/personalData", () => { const makeRequest = async ( token: string, templateId: EServiceTemplateId, - body: eserviceTemplateApi.EServiceTemplatePersonalDataUpdateSeed = eserviceTemplateSeed + body: eserviceTemplateApi.EServiceTemplatePersonalDataFlagUpdateSeed = eserviceTemplateSeed ) => request(api) .post(`/templates/${templateId}/personalData`) @@ -128,7 +128,7 @@ describe("API /templates/{templateId}/personalData", () => { const res = await makeRequest( token, templateId as EServiceTemplateId, - body as eserviceTemplateApi.EServiceTemplatePersonalDataUpdateSeed + body as eserviceTemplateApi.EServiceTemplatePersonalDataFlagUpdateSeed ); expect(res.status).toBe(400); From b50243ddfdd52d70c47c221a9293e408fd11b123 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 25 Sep 2025 16:36:24 +0200 Subject: [PATCH 111/180] Renaming --- packages/api-clients/open-api/bffApi.yml | 2 +- packages/api-clients/open-api/eserviceTemplateApi.yml | 2 +- .../src/services/eserviceTemplateService.ts | 2 +- .../updateEServiceTemplatePersonalData.test.ts | 2 +- .../src/routers/EServiceTemplateRouter.ts | 4 ++-- .../src/services/eserviceTemplateService.ts | 2 +- .../api/updateEServiceTemplatePersonalData.test.ts | 7 +++---- ...viceTemplatePersonalDataUpdatedAfterPublish.test.ts | 10 +++++----- 8 files changed, 15 insertions(+), 16 deletions(-) diff --git a/packages/api-clients/open-api/bffApi.yml b/packages/api-clients/open-api/bffApi.yml index 791a5757e8..fe4b985042 100644 --- a/packages/api-clients/open-api/bffApi.yml +++ b/packages/api-clients/open-api/bffApi.yml @@ -19975,7 +19975,7 @@ paths: tags: - eserviceTemplates summary: Set personalData flag for published EService templates - operationId: updateEServiceTemplatePersonalDataAfterPublish + operationId: updateEServiceTemplatePersonalDataFlagAfterPublication parameters: - name: eServiceTemplateId in: path diff --git a/packages/api-clients/open-api/eserviceTemplateApi.yml b/packages/api-clients/open-api/eserviceTemplateApi.yml index bc03496c99..54c355d3f1 100644 --- a/packages/api-clients/open-api/eserviceTemplateApi.yml +++ b/packages/api-clients/open-api/eserviceTemplateApi.yml @@ -1179,7 +1179,7 @@ paths: tags: - process summary: Set personalData flag for published e-service templates - operationId: updateEServiceTemplatePersonalDataAfterPublish + operationId: updateEServiceTemplatePersonalDataFlagAfterPublication parameters: - name: templateId in: path diff --git a/packages/backend-for-frontend/src/services/eserviceTemplateService.ts b/packages/backend-for-frontend/src/services/eserviceTemplateService.ts index 125a87c200..c70d8188e4 100644 --- a/packages/backend-for-frontend/src/services/eserviceTemplateService.ts +++ b/packages/backend-for-frontend/src/services/eserviceTemplateService.ts @@ -663,7 +663,7 @@ export function eserviceTemplateServiceBuilder( logger.info( `Set personal flag for E-Service Template with id = ${templateId} to ${personalDataSeed.personalData}` ); - await eserviceTemplateClient.updateEServiceTemplatePersonalDataAfterPublish( + await eserviceTemplateClient.updateEServiceTemplatePersonalDataFlagAfterPublication( personalDataSeed, { headers, diff --git a/packages/backend-for-frontend/test/api/eserviceTemplateRouter/updateEServiceTemplatePersonalData.test.ts b/packages/backend-for-frontend/test/api/eserviceTemplateRouter/updateEServiceTemplatePersonalData.test.ts index e841931548..c5491401e2 100644 --- a/packages/backend-for-frontend/test/api/eserviceTemplateRouter/updateEServiceTemplatePersonalData.test.ts +++ b/packages/backend-for-frontend/test/api/eserviceTemplateRouter/updateEServiceTemplatePersonalData.test.ts @@ -20,7 +20,7 @@ describe("API POST /eservices/templates/:eServiceTemplateId/personalData", () => getMockBffApiEServiceTemplatePersonalDataFlagUpdateSeed(); beforeEach(() => { - clients.eserviceTemplateProcessClient.updateEServiceTemplatePersonalDataAfterPublish = + clients.eserviceTemplateProcessClient.updateEServiceTemplatePersonalDataFlagAfterPublication = vi.fn().mockResolvedValue(mockEServiceTemplate); }); diff --git a/packages/eservice-template-process/src/routers/EServiceTemplateRouter.ts b/packages/eservice-template-process/src/routers/EServiceTemplateRouter.ts index 3b9cf9ffdf..ec9bb35eb6 100644 --- a/packages/eservice-template-process/src/routers/EServiceTemplateRouter.ts +++ b/packages/eservice-template-process/src/routers/EServiceTemplateRouter.ts @@ -698,7 +698,7 @@ const eserviceTemplatesRouter = ( } } ) - .post("/templates/:templateId/personalData", async (req, res) => { + .post("/templates/:templateId/personalDataFlag", async (req, res) => { const ctx = fromAppContext(req.ctx); try { @@ -709,7 +709,7 @@ const eserviceTemplatesRouter = ( } const updatedEServiceTemplate = - await eserviceTemplateService.updateEServiceTemplatePersonalDataAfterPublish( + await eserviceTemplateService.updateEServiceTemplatePersonalDataFlagAfterPublication( unsafeBrandId(req.params.templateId), req.body.personalData, ctx diff --git a/packages/eservice-template-process/src/services/eserviceTemplateService.ts b/packages/eservice-template-process/src/services/eserviceTemplateService.ts index 296a5aa4dd..cdf00022b4 100644 --- a/packages/eservice-template-process/src/services/eserviceTemplateService.ts +++ b/packages/eservice-template-process/src/services/eserviceTemplateService.ts @@ -1794,7 +1794,7 @@ export function eserviceTemplateServiceBuilder( await repository.createEvent(event); }, - async updateEServiceTemplatePersonalDataAfterPublish( + async updateEServiceTemplatePersonalDataFlagAfterPublication( eserviceTemplateId: EServiceTemplateId, personalData: boolean, { authData, correlationId, logger }: WithLogger> diff --git a/packages/eservice-template-process/test/api/updateEServiceTemplatePersonalData.test.ts b/packages/eservice-template-process/test/api/updateEServiceTemplatePersonalData.test.ts index 04b458aeb0..eefd76ad6b 100644 --- a/packages/eservice-template-process/test/api/updateEServiceTemplatePersonalData.test.ts +++ b/packages/eservice-template-process/test/api/updateEServiceTemplatePersonalData.test.ts @@ -48,9 +48,8 @@ describe("API /templates/{templateId}/personalData", () => { const eserviceTemplateSeed: eserviceTemplateApi.EServiceTemplatePersonalDataFlagUpdateSeed = { personalData }; - eserviceTemplateService.updateEServiceTemplatePersonalDataAfterPublish = vi - .fn() - .mockResolvedValue(serviceResponse); + eserviceTemplateService.updateEServiceTemplatePersonalDataFlagAfterPublication = + vi.fn().mockResolvedValue(serviceResponse); const makeRequest = async ( token: string, @@ -107,7 +106,7 @@ describe("API /templates/{templateId}/personalData", () => { ])( "Should return $expectedStatus for $error.code", async ({ error, expectedStatus }) => { - eserviceTemplateService.updateEServiceTemplatePersonalDataAfterPublish = + eserviceTemplateService.updateEServiceTemplatePersonalDataFlagAfterPublication = vi.fn().mockRejectedValue(error); const token = generateToken(authRole.ADMIN_ROLE); diff --git a/packages/eservice-template-process/test/integration/updateEServiceTemplatePersonalDataUpdatedAfterPublish.test.ts b/packages/eservice-template-process/test/integration/updateEServiceTemplatePersonalDataUpdatedAfterPublish.test.ts index 9df6f762e8..add3d4667c 100644 --- a/packages/eservice-template-process/test/integration/updateEServiceTemplatePersonalDataUpdatedAfterPublish.test.ts +++ b/packages/eservice-template-process/test/integration/updateEServiceTemplatePersonalDataUpdatedAfterPublish.test.ts @@ -44,7 +44,7 @@ describe("update EService Template personalData flag for an already created ESer const newPersonalDataValue = true; const returnedEServiceTemplate = - await eserviceTemplateService.updateEServiceTemplatePersonalDataAfterPublish( + await eserviceTemplateService.updateEServiceTemplatePersonalDataFlagAfterPublication( eserviceTemplate.id, newPersonalDataValue, getMockContext({ @@ -101,7 +101,7 @@ describe("update EService Template personalData flag for an already created ESer await addOneEServiceTemplate(eserviceTemplate); await expect( - eserviceTemplateService.updateEServiceTemplatePersonalDataAfterPublish( + eserviceTemplateService.updateEServiceTemplatePersonalDataFlagAfterPublication( eserviceTemplate.id, newValue, getMockContext({ @@ -120,7 +120,7 @@ describe("update EService Template personalData flag for an already created ESer const eserviceTemplate = getMockEServiceTemplate(); await expect( - eserviceTemplateService.updateEServiceTemplatePersonalDataAfterPublish( + eserviceTemplateService.updateEServiceTemplatePersonalDataFlagAfterPublication( eserviceTemplate.id, personalDataFlag, getMockContext({ @@ -138,7 +138,7 @@ describe("update EService Template personalData flag for an already created ESer await addOneEServiceTemplate(eserviceTemplate); await expect( - eserviceTemplateService.updateEServiceTemplatePersonalDataAfterPublish( + eserviceTemplateService.updateEServiceTemplatePersonalDataFlagAfterPublication( eserviceTemplate.id, personalDataFlag, getMockContext({}) @@ -158,7 +158,7 @@ describe("update EService Template personalData flag for an already created ESer await addOneEServiceTemplate(eserviceTemplate); await expect( - eserviceTemplateService.updateEServiceTemplatePersonalDataAfterPublish( + eserviceTemplateService.updateEServiceTemplatePersonalDataFlagAfterPublication( eserviceTemplate.id, personalDataFlag, getMockContext({ From ac326b230ab7a72b2ebfdba45e3a4e2a79a9cd9b Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 25 Sep 2025 16:42:55 +0200 Subject: [PATCH 112/180] Fix --- packages/api-clients/open-api/catalogApi.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/api-clients/open-api/catalogApi.yml b/packages/api-clients/open-api/catalogApi.yml index bb6ef962a4..52cdc81304 100644 --- a/packages/api-clients/open-api/catalogApi.yml +++ b/packages/api-clients/open-api/catalogApi.yml @@ -2296,7 +2296,7 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/EServicePersonalDataUpdateSeed" + $ref: "#/components/schemas/EServiceTemplatePersonalDataFlagUpdateSeed" operationId: setTemplateInstancePersonalData description: Update the personalData flag of a template instance after a template update responses: From 4faa757c2950f529bd7053835b40c63c00bfed0f Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 25 Sep 2025 17:03:26 +0200 Subject: [PATCH 113/180] Fix --- .../backend-for-frontend/src/routers/eserviceTemplateRouter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend-for-frontend/src/routers/eserviceTemplateRouter.ts b/packages/backend-for-frontend/src/routers/eserviceTemplateRouter.ts index 8392d28bc4..b86a08da2f 100644 --- a/packages/backend-for-frontend/src/routers/eserviceTemplateRouter.ts +++ b/packages/backend-for-frontend/src/routers/eserviceTemplateRouter.ts @@ -321,7 +321,7 @@ const eserviceTemplateRouter = ( } ) .post( - "/eservices/templates/:eServiceTemplateId/personalData", + "/eservices/templates/:eServiceTemplateId/personalDataFlag", async (req, res) => { const ctx = fromBffAppContext(req.ctx, req.headers); try { From 204b88cf1520b6197c97a24273fa2f114d5c23c6 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 25 Sep 2025 17:13:30 +0200 Subject: [PATCH 114/180] Fix --- packages/api-clients/open-api/catalogApi.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/api-clients/open-api/catalogApi.yml b/packages/api-clients/open-api/catalogApi.yml index 52cdc81304..060541436f 100644 --- a/packages/api-clients/open-api/catalogApi.yml +++ b/packages/api-clients/open-api/catalogApi.yml @@ -2296,7 +2296,7 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/EServiceTemplatePersonalDataFlagUpdateSeed" + $ref: "#/components/schemas/EServicePersonalDataFlagUpdateSeed" operationId: setTemplateInstancePersonalData description: Update the personalData flag of a template instance after a template update responses: From 6cd70533a4af5a6e195f2e8c44449eeeb315fd22 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 25 Sep 2025 17:25:13 +0200 Subject: [PATCH 115/180] Fix test --- .../test/api/updateEServiceTemplatePersonalData.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/eservice-template-process/test/api/updateEServiceTemplatePersonalData.test.ts b/packages/eservice-template-process/test/api/updateEServiceTemplatePersonalData.test.ts index eefd76ad6b..6d69aa1f14 100644 --- a/packages/eservice-template-process/test/api/updateEServiceTemplatePersonalData.test.ts +++ b/packages/eservice-template-process/test/api/updateEServiceTemplatePersonalData.test.ts @@ -26,7 +26,7 @@ import { eserviceTemplatePersonalDataCanOnlyBeSetOnce, } from "../../src/model/domain/errors.js"; -describe("API /templates/{templateId}/personalData", () => { +describe("API /templates/{templateId}/personalDataFlag", () => { const eserviceTemplateVersion: EServiceTemplateVersion = { ...getMockEServiceTemplateVersion(), state: eserviceTemplateVersionState.published, @@ -57,7 +57,7 @@ describe("API /templates/{templateId}/personalData", () => { body: eserviceTemplateApi.EServiceTemplatePersonalDataFlagUpdateSeed = eserviceTemplateSeed ) => request(api) - .post(`/templates/${templateId}/personalData`) + .post(`/templates/${templateId}/personalDataFlag`) .set("Authorization", `Bearer ${token}`) .set("X-Correlation-Id", generateId()) .send(body); From 03d0f4b03c9bcc9a6af578d67af6f40807fc257f Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 25 Sep 2025 17:51:26 +0200 Subject: [PATCH 116/180] Add bruno collections --- .../Set EService PersonalData Flag.bru | 26 +++++++++++++++++++ .../Set EService PersonalData Flag.bru | 26 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 collections/bff/catalog/Set EService PersonalData Flag.bru create mode 100644 collections/catalog/Set EService PersonalData Flag.bru diff --git a/collections/bff/catalog/Set EService PersonalData Flag.bru b/collections/bff/catalog/Set EService PersonalData Flag.bru new file mode 100644 index 0000000000..90863c0db5 --- /dev/null +++ b/collections/bff/catalog/Set EService PersonalData Flag.bru @@ -0,0 +1,26 @@ +meta { + name: Set EService PersonalData Flag + type: http + seq: 35 +} + +post { + url: {{host-bff}}/eservices/:eServiceId/personalDataFlag + body: json + auth: none +} + +params:path { + eServiceId: {{eServiceId}} +} + +headers { + Authorization: {{JWT}} + X-Correlation-Id: {{correlation-id}} +} + +body:json { + { + "personalData": true + } +} diff --git a/collections/catalog/Set EService PersonalData Flag.bru b/collections/catalog/Set EService PersonalData Flag.bru new file mode 100644 index 0000000000..830e93322a --- /dev/null +++ b/collections/catalog/Set EService PersonalData Flag.bru @@ -0,0 +1,26 @@ +meta { + name: Set EService PersonalData Flag + type: http + seq: 35 +} + +post { + url: {{host-catalog}}/eservices/:eServiceId/personalDataFlag + body: json + auth: none +} + +params:path { + eServiceId: {{eServiceId}} +} + +headers { + Authorization: {{JWT}} + X-Correlation-Id: {{correlation-id}} +} + +body:json { + { + "personalData": true + } +} From 7491715ad9e90e8638d71b3dc39e6a85b6168211 Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Fri, 26 Sep 2025 09:11:03 +0200 Subject: [PATCH 117/180] chore(backend-for-frontend): remove redundant getMockBffApiEServicePersonalData mock --- .../api/catalogRouter/updateEServicePersonalData.test.ts | 4 ++-- packages/backend-for-frontend/test/mockUtils.ts | 7 ------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/packages/backend-for-frontend/test/api/catalogRouter/updateEServicePersonalData.test.ts b/packages/backend-for-frontend/test/api/catalogRouter/updateEServicePersonalData.test.ts index 59df11a655..44df8a899c 100644 --- a/packages/backend-for-frontend/test/api/catalogRouter/updateEServicePersonalData.test.ts +++ b/packages/backend-for-frontend/test/api/catalogRouter/updateEServicePersonalData.test.ts @@ -8,14 +8,14 @@ import { bffApi } from "pagopa-interop-api-clients"; import { api, clients } from "../../vitest.api.setup.js"; import { getMockBffApiEServicePersonalDataFlagUpdateSeed, - getMockBffApiEServicePersonaData, + getMockCatalogApiEService, } from "../../mockUtils.js"; import { appBasePath } from "../../../src/config/appBasePath.js"; describe("API POST /eservices/:eServiceId/personalDataFlag", () => { const mockEServicePersonalDataFlagUpdateSeed = getMockBffApiEServicePersonalDataFlagUpdateSeed(); - const mockEService = getMockBffApiEServicePersonaData(); + const mockEService = getMockCatalogApiEService(); const makeRequest = async ( token: string, diff --git a/packages/backend-for-frontend/test/mockUtils.ts b/packages/backend-for-frontend/test/mockUtils.ts index 8b1936c71c..24567fcf13 100644 --- a/packages/backend-for-frontend/test/mockUtils.ts +++ b/packages/backend-for-frontend/test/mockUtils.ts @@ -284,13 +284,6 @@ export const getMockCatalogApiEService = (): catalogApi.EService & { personalData: generateMock(z.boolean().optional()), }); -export const getMockBffApiEServicePersonaData = (): catalogApi.EService & { - id: EServiceId; -} => ({ - ...getMockCatalogApiEService(), - personalData: generateMock(z.boolean().optional()), -}); - export const getMockBffApiFileResource = (): bffApi.FileResource => ({ url: generateMock(z.string().url()), filename: generateMock(z.string()), From d9a6d044a07906c5859d154e410b2c217bb8f6b4 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Fri, 26 Sep 2025 09:12:49 +0200 Subject: [PATCH 118/180] Rename test file --- ...ata.test.ts => updateEServiceTemplatePersonalDataFlag.test.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/eservice-template-process/test/api/{updateEServiceTemplatePersonalData.test.ts => updateEServiceTemplatePersonalDataFlag.test.ts} (100%) diff --git a/packages/eservice-template-process/test/api/updateEServiceTemplatePersonalData.test.ts b/packages/eservice-template-process/test/api/updateEServiceTemplatePersonalDataFlag.test.ts similarity index 100% rename from packages/eservice-template-process/test/api/updateEServiceTemplatePersonalData.test.ts rename to packages/eservice-template-process/test/api/updateEServiceTemplatePersonalDataFlag.test.ts From b8ccaf2b2448e5499d5a954c912d96ff77e0f3aa Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Fri, 26 Sep 2025 09:43:46 +0200 Subject: [PATCH 119/180] chore(backend-for-frontend): remove redundant getMockBffApiEServiceTemplatePersonalData mock --- .../updateEServiceTemplatePersonalData.test.ts | 8 +++----- packages/backend-for-frontend/test/mockUtils.ts | 7 ------- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/packages/backend-for-frontend/test/api/eserviceTemplateRouter/updateEServiceTemplatePersonalData.test.ts b/packages/backend-for-frontend/test/api/eserviceTemplateRouter/updateEServiceTemplatePersonalData.test.ts index c5491401e2..669e86b0e6 100644 --- a/packages/backend-for-frontend/test/api/eserviceTemplateRouter/updateEServiceTemplatePersonalData.test.ts +++ b/packages/backend-for-frontend/test/api/eserviceTemplateRouter/updateEServiceTemplatePersonalData.test.ts @@ -8,14 +8,12 @@ import { bffApi } from "pagopa-interop-api-clients"; import { api, clients } from "../../vitest.api.setup.js"; import { appBasePath } from "../../../src/config/appBasePath.js"; import { - getMockBffApiEServiceTemplatePersonaData, + getMockBffApiEServiceTemplate, getMockBffApiEServiceTemplatePersonalDataFlagUpdateSeed, } from "../../mockUtils.js"; -describe("API POST /eservices/templates/:eServiceTemplateId/personalData", () => { - const mockEServiceTemplate = { - ...getMockBffApiEServiceTemplatePersonaData(), - }; +describe("API POST /eservices/templates/:eServiceTemplateId/personalDataFlag", () => { + const mockEServiceTemplate = getMockBffApiEServiceTemplate(); const mockEServiceTemplatePersonalDataFlagUpdateSeed = getMockBffApiEServiceTemplatePersonalDataFlagUpdateSeed(); diff --git a/packages/backend-for-frontend/test/mockUtils.ts b/packages/backend-for-frontend/test/mockUtils.ts index 4470eb32ef..a4fe0b2d5c 100644 --- a/packages/backend-for-frontend/test/mockUtils.ts +++ b/packages/backend-for-frontend/test/mockUtils.ts @@ -667,13 +667,6 @@ export const getMockBffApiEServiceTemplate = ), mode: generateMock(eserviceTemplateApi.EServiceMode), isSignalHubEnabled: generateMock(z.boolean().optional()), - }); - -export const getMockBffApiEServiceTemplatePersonaData = - (): eserviceTemplateApi.EServiceTemplate & { - id: EServiceTemplateId; - } => ({ - ...getMockBffApiEServiceTemplate(), personalData: generateMock(z.boolean().optional()), }); From af691b5015b610f53d6f12209ba22ffaa6092976 Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Fri, 26 Sep 2025 09:56:52 +0200 Subject: [PATCH 120/180] test(backend-for-frontend): renamed API POST /eservices/templates/:eServiceTemplateId/personalDataFlag --- .../updateEServiceTemplatePersonalData.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend-for-frontend/test/api/eserviceTemplateRouter/updateEServiceTemplatePersonalData.test.ts b/packages/backend-for-frontend/test/api/eserviceTemplateRouter/updateEServiceTemplatePersonalData.test.ts index 669e86b0e6..12d090193a 100644 --- a/packages/backend-for-frontend/test/api/eserviceTemplateRouter/updateEServiceTemplatePersonalData.test.ts +++ b/packages/backend-for-frontend/test/api/eserviceTemplateRouter/updateEServiceTemplatePersonalData.test.ts @@ -29,7 +29,7 @@ describe("API POST /eservices/templates/:eServiceTemplateId/personalDataFlag", ( ) => request(api) .post( - `${appBasePath}/eservices/templates/${eServiceTemplateId}/personalData` + `${appBasePath}/eservices/templates/${eServiceTemplateId}/personalDataFlag` ) .set("Authorization", `Bearer ${token}`) .set("X-Correlation-Id", generateId()) From 993ec4b6e71634f3640d61c0bba3c848254271a2 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Fri, 26 Sep 2025 15:44:17 +0200 Subject: [PATCH 121/180] Fix converter --- .../eservice-template-process/src/model/domain/apiConverter.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/eservice-template-process/src/model/domain/apiConverter.ts b/packages/eservice-template-process/src/model/domain/apiConverter.ts index c9fc76741f..d923f85026 100644 --- a/packages/eservice-template-process/src/model/domain/apiConverter.ts +++ b/packages/eservice-template-process/src/model/domain/apiConverter.ts @@ -170,4 +170,5 @@ export const eserviceTemplateToApiEServiceTemplate = ( eserviceTemplateVersionToApiEServiceTemplateVersion ), isSignalHubEnabled: eserviceTemplate.isSignalHubEnabled, + personalData: eserviceTemplate.personalData, }); From 08e31c1167bf65bbbebe798a5bcb0e6b2d654091 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Fri, 26 Sep 2025 15:50:38 +0200 Subject: [PATCH 122/180] Fix converter --- packages/m2m-gateway/src/api/eserviceTemplateApiConverter.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/m2m-gateway/src/api/eserviceTemplateApiConverter.ts b/packages/m2m-gateway/src/api/eserviceTemplateApiConverter.ts index e5c7d9b55c..2610517e25 100644 --- a/packages/m2m-gateway/src/api/eserviceTemplateApiConverter.ts +++ b/packages/m2m-gateway/src/api/eserviceTemplateApiConverter.ts @@ -12,6 +12,7 @@ export function toM2MGatewayEServiceTemplate( name: template.name, technology: template.technology, isSignalHubEnabled: template.isSignalHubEnabled, + personalData: template.personalData, }; } From 4ea2e625de91510e717b54bb5738ee45c6c1e189 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Fri, 26 Sep 2025 16:23:11 +0200 Subject: [PATCH 123/180] Add bruno collections --- ...et EService Template PersonalData Flag.bru | 25 +++++++++++++++++++ ...et EService Template PersonalData Flag.bru | 25 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 collections/bff/eserviceTemplate/Set EService Template PersonalData Flag.bru create mode 100644 collections/eservice-template/Set EService Template PersonalData Flag.bru diff --git a/collections/bff/eserviceTemplate/Set EService Template PersonalData Flag.bru b/collections/bff/eserviceTemplate/Set EService Template PersonalData Flag.bru new file mode 100644 index 0000000000..668659b50c --- /dev/null +++ b/collections/bff/eserviceTemplate/Set EService Template PersonalData Flag.bru @@ -0,0 +1,25 @@ +meta { + name: Set EService Template PersonalData Flag + type: http + seq: 18 +} + +post { + url: {{host-bff}}/templates/:eserviceTemplateId/personalDataFlag + body: json + auth: none +} + +params:path { + eserviceTemplateId: {{eserviceTemplateId}} +} + +headers { + Authorization: {{JWT}} + X-Correlation-Id: {{correlation-id}} + Content-Type: application/json +} + +body:json { + "personalData": true +} diff --git a/collections/eservice-template/Set EService Template PersonalData Flag.bru b/collections/eservice-template/Set EService Template PersonalData Flag.bru new file mode 100644 index 0000000000..40112e7cdc --- /dev/null +++ b/collections/eservice-template/Set EService Template PersonalData Flag.bru @@ -0,0 +1,25 @@ +meta { + name: Set EService Template PersonalData Flag + type: http + seq: 18 +} + +post { + url: {{host-template}}/templates/:eserviceTemplateId/personalDataFlag + body: json + auth: none +} + +params:path { + eserviceTemplateId: {{eserviceTemplateId}} +} + +headers { + Authorization: {{JWT}} + X-Correlation-Id: {{correlation-id}} + Content-Type: application/json +} + +body:json { + "personalData": true +} From d9cd51bc5f7a475db923faaa6568893e62b3e91d Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 29 Sep 2025 11:48:25 +0200 Subject: [PATCH 124/180] Renaming --- packages/api-clients/open-api/catalogApi.yml | 4 ++-- .../catalog-process/src/routers/EServiceRouter.ts | 2 +- ...viceTemplateInstancesUpdaterConsumerServiceV2.ts | 2 +- ...emplateInstancesUpdaterConsumerServiceV2.test.ts | 13 +++++++------ 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/packages/api-clients/open-api/catalogApi.yml b/packages/api-clients/open-api/catalogApi.yml index 060541436f..a62f8749cd 100644 --- a/packages/api-clients/open-api/catalogApi.yml +++ b/packages/api-clients/open-api/catalogApi.yml @@ -2277,7 +2277,7 @@ paths: application/problem+json: schema: $ref: "#/components/schemas/Problem" - /internal/templates/eservices/{eServiceId}/personalData/set: + /internal/templates/eservices/{eServiceId}/personalDataFlag/set: post: parameters: - $ref: "#/components/parameters/CorrelationIdHeader" @@ -2297,7 +2297,7 @@ paths: application/json: schema: $ref: "#/components/schemas/EServicePersonalDataFlagUpdateSeed" - operationId: setTemplateInstancePersonalData + operationId: setTemplateInstancePersonalDataFlag description: Update the personalData flag of a template instance after a template update responses: "204": diff --git a/packages/catalog-process/src/routers/EServiceRouter.ts b/packages/catalog-process/src/routers/EServiceRouter.ts index 43e3a190c5..33a93c81e9 100644 --- a/packages/catalog-process/src/routers/EServiceRouter.ts +++ b/packages/catalog-process/src/routers/EServiceRouter.ts @@ -1236,7 +1236,7 @@ const eservicesRouter = ( } ) .post( - "/internal/templates/eservices/:eServiceId/personalData/set", + "/internal/templates/eservices/:eServiceId/personalDataFlag/set", async (req, res) => { const ctx = fromAppContext(req.ctx); diff --git a/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts b/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts index 0892dd6211..2f1b658b03 100644 --- a/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts +++ b/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts @@ -345,7 +345,7 @@ export async function handleMessageV2({ instance: EService, headers: InteropHeaders ): Promise => { - await catalogProcess.client.setTemplateInstancePersonalData( + await catalogProcess.client.setTemplateInstancePersonalDataFlag( { personalData }, { params: { diff --git a/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts b/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts index 34c08b0821..aedad496f5 100644 --- a/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts +++ b/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts @@ -42,7 +42,7 @@ const updateTemplateInstanceDescriptorVoucherLifespanFn = vi.fn(); const createTemplateInstanceDescriptorDocumentFn = vi.fn(); const updateTemplateInstanceDescriptorDocumentFn = vi.fn(); const deleteTemplateInstanceDescriptorDocumentFn = vi.fn(); -const setTemplateInstancePersonalDataFn = vi.fn(); +const setTemplateInstancePersonalDataFlagFn = vi.fn(); const copyDocumentFn = vi.fn(); @@ -66,7 +66,8 @@ vi.doMock("pagopa-interop-api-clients", () => ({ updateTemplateInstanceDescriptorDocumentFn, deleteTemplateInstanceDescriptorDocument: deleteTemplateInstanceDescriptorDocumentFn, - setTemplateInstancePersonalData: setTemplateInstancePersonalDataFn, + setTemplateInstancePersonalDataFlag: + setTemplateInstancePersonalDataFlagFn, }), }, })); @@ -942,8 +943,8 @@ describe("eserviceTemplateUpdaterConsumerServiceV2", () => { fileManager, }); - expect(setTemplateInstancePersonalDataFn).toHaveBeenCalledTimes(3); - expect(setTemplateInstancePersonalDataFn).toHaveBeenCalledWith( + expect(setTemplateInstancePersonalDataFlagFn).toHaveBeenCalledTimes(3); + expect(setTemplateInstancePersonalDataFlagFn).toHaveBeenCalledWith( { personalData: mockTemplate.personalData }, { params: { @@ -952,7 +953,7 @@ describe("eserviceTemplateUpdaterConsumerServiceV2", () => { headers: testHeaders, } ); - expect(setTemplateInstancePersonalDataFn).toHaveBeenCalledWith( + expect(setTemplateInstancePersonalDataFlagFn).toHaveBeenCalledWith( { personalData: mockTemplate.personalData }, { params: { @@ -961,7 +962,7 @@ describe("eserviceTemplateUpdaterConsumerServiceV2", () => { headers: testHeaders, } ); - expect(setTemplateInstancePersonalDataFn).toHaveBeenCalledWith( + expect(setTemplateInstancePersonalDataFlagFn).toHaveBeenCalledWith( { personalData: mockTemplate.personalData }, { params: { From d780668cdbe12730b70b0881bddb602e29bb01e8 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 29 Sep 2025 11:54:54 +0200 Subject: [PATCH 125/180] Renaming --- packages/catalog-process/src/routers/EServiceRouter.ts | 2 +- packages/catalog-process/src/services/catalogService.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/catalog-process/src/routers/EServiceRouter.ts b/packages/catalog-process/src/routers/EServiceRouter.ts index 33a93c81e9..e0a215ec55 100644 --- a/packages/catalog-process/src/routers/EServiceRouter.ts +++ b/packages/catalog-process/src/routers/EServiceRouter.ts @@ -1243,7 +1243,7 @@ const eservicesRouter = ( try { validateAuthorization(ctx, [INTERNAL_ROLE]); - await catalogService.internalUpdateTemplateInstancePersonalData( + await catalogService.internalUpdateTemplateInstancePersonalDataFlag( unsafeBrandId(req.params.eServiceId), req.body.personalData, ctx diff --git a/packages/catalog-process/src/services/catalogService.ts b/packages/catalog-process/src/services/catalogService.ts index a13781d58a..3400ee310e 100644 --- a/packages/catalog-process/src/services/catalogService.ts +++ b/packages/catalog-process/src/services/catalogService.ts @@ -2923,7 +2923,7 @@ export function catalogServiceBuilder( ) ); }, - async internalUpdateTemplateInstancePersonalData( + async internalUpdateTemplateInstancePersonalDataFlag( eserviceId: EServiceId, personalData: boolean, { correlationId, logger }: WithLogger From 3ea8d3464ac4419761c98c707f7923012c686262 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 29 Sep 2025 17:06:35 +0200 Subject: [PATCH 126/180] Update logic and test to cover descriptor approval --- .../src/services/catalogService.ts | 7 +++++ .../src/utilities/errorMappers.ts | 1 + ...approveDelegatedEServiceDescriptor.test.ts | 5 ++++ ...approveDelegatedEServiceDescriptor.test.ts | 29 +++++++++++++++++-- 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/packages/catalog-process/src/services/catalogService.ts b/packages/catalog-process/src/services/catalogService.ts index b49322320e..6dad76189f 100644 --- a/packages/catalog-process/src/services/catalogService.ts +++ b/packages/catalog-process/src/services/catalogService.ts @@ -2720,6 +2720,13 @@ export function catalogServiceBuilder( ); } + if ( + config.featureFlagEservicePersonalData && + eservice.data.personalData === undefined + ) { + throw missingPersonalDataFlag(eserviceId, descriptorId); + } + const updatedEService = await processDescriptorPublication( eservice.data, descriptor, diff --git a/packages/catalog-process/src/utilities/errorMappers.ts b/packages/catalog-process/src/utilities/errorMappers.ts index aa144928d2..4534b5d141 100644 --- a/packages/catalog-process/src/utilities/errorMappers.ts +++ b/packages/catalog-process/src/utilities/errorMappers.ts @@ -508,6 +508,7 @@ export const approveDelegatedEServiceDescriptorErrorMapper = ( "eServiceDescriptorNotFound", () => HTTP_STATUS_NOT_FOUND ) + .with("missingPersonalDataFlag", () => HTTP_STATUS_BAD_REQUEST) .with("operationForbidden", () => HTTP_STATUS_FORBIDDEN) .otherwise(() => HTTP_STATUS_INTERNAL_SERVER_ERROR); diff --git a/packages/catalog-process/test/api/approveDelegatedEServiceDescriptor.test.ts b/packages/catalog-process/test/api/approveDelegatedEServiceDescriptor.test.ts index 7be9fac8be..69dac19ee6 100644 --- a/packages/catalog-process/test/api/approveDelegatedEServiceDescriptor.test.ts +++ b/packages/catalog-process/test/api/approveDelegatedEServiceDescriptor.test.ts @@ -22,6 +22,7 @@ import { api, catalogService } from "../vitest.api.setup.js"; import { eServiceDescriptorNotFound, eServiceNotFound, + missingPersonalDataFlag, } from "../../src/model/domain/errors.js"; import { eServiceToApiEService } from "../../src/model/domain/apiConverter.js"; @@ -96,6 +97,10 @@ describe("API /eservices/:eServiceId/descriptors/:descriptorId/approve authoriza error: operationForbidden, expectedStatus: 403, }, + { + error: missingPersonalDataFlag(mockEService.id, descriptor.id), + expectedStatus: 400, + }, ])( "Should return $expectedStatus for $error.code", async ({ error, expectedStatus }) => { diff --git a/packages/catalog-process/test/integration/approveDelegatedEServiceDescriptor.test.ts b/packages/catalog-process/test/integration/approveDelegatedEServiceDescriptor.test.ts index 91c8879263..0e55b64a5f 100644 --- a/packages/catalog-process/test/integration/approveDelegatedEServiceDescriptor.test.ts +++ b/packages/catalog-process/test/integration/approveDelegatedEServiceDescriptor.test.ts @@ -28,6 +28,7 @@ import { eServiceNotFound, eServiceDescriptorNotFound, notValidDescriptorState, + missingPersonalDataFlag, } from "../../src/model/domain/errors.js"; import { addOneEService, @@ -38,8 +39,8 @@ import { addOneDelegation, } from "../integrationUtils.js"; -describe("publish descriptor", () => { - const mockEService = getMockEService(); +describe("publish descriptor (after delegator's approval)", () => { + const mockEService: EService = { ...getMockEService(), personalData: false }; const mockDescriptor = getMockDescriptor(); const mockDocument = getMockDocument(); beforeAll(() => { @@ -335,4 +336,28 @@ describe("publish descriptor", () => { ).rejects.toThrowError(notValidDescriptorState(descriptor.id, state)); } ); + + it("should throw missingPersonalDataFlag if the eservice has personalData undefined", async () => { + const descriptor: Descriptor = { + ...mockDescriptor, + state: descriptorState.draft, + interface: mockDocument, + }; + + const eservice: EService = { + ...mockEService, + descriptors: [descriptor], + personalData: undefined, + }; + + await addOneEService(eservice); + + expect( + catalogService.publishDescriptor( + eservice.id, + descriptor.id, + getMockContext({ authData: getMockAuthData(eservice.producerId) }) + ) + ).rejects.toThrowError(missingPersonalDataFlag(eservice.id, descriptor.id)); + }); }); From 40e4e4a545627b84766d9b44d3029ee802a6dc9e Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Tue, 30 Sep 2025 11:18:49 +0200 Subject: [PATCH 127/180] Update api description --- packages/api-clients/open-api/catalogApi.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/api-clients/open-api/catalogApi.yml b/packages/api-clients/open-api/catalogApi.yml index a62f8749cd..828743eff0 100644 --- a/packages/api-clients/open-api/catalogApi.yml +++ b/packages/api-clients/open-api/catalogApi.yml @@ -2301,7 +2301,7 @@ paths: description: Update the personalData flag of a template instance after a template update responses: "204": - description: E-Service personalData updated + description: E-Service personalData flag updated "404": description: E-Service Not Found content: From 167d297fc2beec40785f404d6a411172cc02da2b Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Tue, 30 Sep 2025 11:23:14 +0200 Subject: [PATCH 128/180] Renaming --- packages/catalog-process/src/model/domain/errors.ts | 6 +++--- packages/catalog-process/src/services/catalogService.ts | 4 ++-- packages/catalog-process/src/utilities/errorMappers.ts | 2 +- ... updateEServicePersonalDataFlagAfterPublication.test.ts} | 6 ++++-- 4 files changed, 10 insertions(+), 8 deletions(-) rename packages/catalog-process/test/integration/{updateEServicePersonalDataUpdatedAfterPublish.test.ts => updateEServicePersonalDataFlagAfterPublication.test.ts} (96%) diff --git a/packages/catalog-process/src/model/domain/errors.ts b/packages/catalog-process/src/model/domain/errors.ts index 2f5a193bbc..c49aa0c777 100644 --- a/packages/catalog-process/src/model/domain/errors.ts +++ b/packages/catalog-process/src/model/domain/errors.ts @@ -55,7 +55,7 @@ export const errorCodes = { eserviceTemplateNameConflict: "0039", checksumDuplicate: "0040", attributeDuplicatedInGroup: "0041", - eservicePersonalDataCanOnlyBeSetOnce: "0042", + eservicePersonalDataFlagCanOnlyBeSetOnce: "0042", }; export type ErrorCodes = keyof typeof errorCodes; @@ -477,12 +477,12 @@ export function attributeDuplicatedInGroup( }); } -export function eservicePersonalDataCanOnlyBeSetOnce( +export function eservicePersonalDataFlagCanOnlyBeSetOnce( eserviceId: EServiceId ): ApiError { return new ApiError({ detail: `PersonalData flag has already been set for eService ${eserviceId}`, - code: "eservicePersonalDataCanOnlyBeSetOnce", + code: "eservicePersonalDataFlagCanOnlyBeSetOnce", title: "EService personalData can only be set once", }); } diff --git a/packages/catalog-process/src/services/catalogService.ts b/packages/catalog-process/src/services/catalogService.ts index 5dc4acd016..b47f64a975 100644 --- a/packages/catalog-process/src/services/catalogService.ts +++ b/packages/catalog-process/src/services/catalogService.ts @@ -100,7 +100,7 @@ import { templateMissingRequiredRiskAnalysis, checksumDuplicate, attributeDuplicatedInGroup, - eservicePersonalDataCanOnlyBeSetOnce, + eservicePersonalDataFlagCanOnlyBeSetOnce, } from "../model/domain/errors.js"; import { ApiGetEServicesFilters, Consumer } from "../model/domain/models.js"; import { @@ -3563,7 +3563,7 @@ export function catalogServiceBuilder( assertEServiceUpdatableAfterPublish(eservice.data); if (eservice.data.personalData !== undefined) { - throw eservicePersonalDataCanOnlyBeSetOnce(eserviceId); + throw eservicePersonalDataFlagCanOnlyBeSetOnce(eserviceId); } const updatedEservice: EService = { diff --git a/packages/catalog-process/src/utilities/errorMappers.ts b/packages/catalog-process/src/utilities/errorMappers.ts index 00c473e869..08c79706e7 100644 --- a/packages/catalog-process/src/utilities/errorMappers.ts +++ b/packages/catalog-process/src/utilities/errorMappers.ts @@ -698,7 +698,7 @@ export const updateEServicePersonalDataErrorMapper = ( ) .with( "eserviceWithoutValidDescriptors", - "eservicePersonalDataCanOnlyBeSetOnce", + "eservicePersonalDataFlagCanOnlyBeSetOnce", () => HTTP_STATUS_CONFLICT ) .otherwise(() => HTTP_STATUS_INTERNAL_SERVER_ERROR); diff --git a/packages/catalog-process/test/integration/updateEServicePersonalDataUpdatedAfterPublish.test.ts b/packages/catalog-process/test/integration/updateEServicePersonalDataFlagAfterPublication.test.ts similarity index 96% rename from packages/catalog-process/test/integration/updateEServicePersonalDataUpdatedAfterPublish.test.ts rename to packages/catalog-process/test/integration/updateEServicePersonalDataFlagAfterPublication.test.ts index 34cbd88ceb..30220fc98f 100644 --- a/packages/catalog-process/test/integration/updateEServicePersonalDataUpdatedAfterPublish.test.ts +++ b/packages/catalog-process/test/integration/updateEServicePersonalDataFlagAfterPublication.test.ts @@ -23,7 +23,7 @@ import { } from "../integrationUtils.js"; import { eServiceNotFound, - eservicePersonalDataCanOnlyBeSetOnce, + eservicePersonalDataFlagCanOnlyBeSetOnce, eserviceWithoutValidDescriptors, } from "../../src/model/domain/errors.js"; @@ -96,7 +96,9 @@ describe("update E-service personalData flag for an already created E-service", newPersonalDataValue, getMockContext({ authData: getMockAuthData(eservice.producerId) }) ) - ).rejects.toThrowError(eservicePersonalDataCanOnlyBeSetOnce(eservice.id)); + ).rejects.toThrowError( + eservicePersonalDataFlagCanOnlyBeSetOnce(eservice.id) + ); } ); From 4855475d88fb56953597ce21f4e2d4727344679d Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Tue, 30 Sep 2025 11:25:09 +0200 Subject: [PATCH 129/180] update error title --- packages/catalog-process/src/model/domain/errors.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/catalog-process/src/model/domain/errors.ts b/packages/catalog-process/src/model/domain/errors.ts index c49aa0c777..a48fd0068d 100644 --- a/packages/catalog-process/src/model/domain/errors.ts +++ b/packages/catalog-process/src/model/domain/errors.ts @@ -483,6 +483,6 @@ export function eservicePersonalDataFlagCanOnlyBeSetOnce( return new ApiError({ detail: `PersonalData flag has already been set for eService ${eserviceId}`, code: "eservicePersonalDataFlagCanOnlyBeSetOnce", - title: "EService personalData can only be set once", + title: "EService personalData flag can only be set once", }); } From 026e9e855b555702e7b787fee127b34b3a800c43 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Tue, 30 Sep 2025 11:33:12 +0200 Subject: [PATCH 130/180] Renaming --- .../eservice-template-process/src/model/domain/errors.ts | 6 +++--- .../src/services/eserviceTemplateService.ts | 6 ++++-- .../eservice-template-process/src/utilities/errorMappers.ts | 2 +- .../test/api/updateEServiceTemplatePersonalDataFlag.test.ts | 4 ++-- ...eEServiceTemplatePersonalDataUpdatedAfterPublish.test.ts | 4 ++-- 5 files changed, 12 insertions(+), 10 deletions(-) diff --git a/packages/eservice-template-process/src/model/domain/errors.ts b/packages/eservice-template-process/src/model/domain/errors.ts index f4f46088d3..2d3ff5f043 100644 --- a/packages/eservice-template-process/src/model/domain/errors.ts +++ b/packages/eservice-template-process/src/model/domain/errors.ts @@ -35,7 +35,7 @@ export const errorCodes = { riskAnalysisNotFound: "0026", attributeDuplicatedInGroup: "0027", missingPersonalDataFlag: "0028", - eserviceTemplatePersonalDataCanOnlyBeSetOnce: "0029", + eserviceTemplatePersonalDataFlagCanOnlyBeSetOnce: "0029", }; export type ErrorCodes = keyof typeof errorCodes; @@ -312,12 +312,12 @@ export function missingPersonalDataFlag( }); } -export function eserviceTemplatePersonalDataCanOnlyBeSetOnce( +export function eserviceTemplatePersonalDataFlagCanOnlyBeSetOnce( eserviceTemplateId: EServiceTemplateId ): ApiError { return new ApiError({ detail: `PersonalData flag has already been set for eService Template ${eserviceTemplateId}`, - code: "eserviceTemplatePersonalDataCanOnlyBeSetOnce", + code: "eserviceTemplatePersonalDataFlagCanOnlyBeSetOnce", title: "EService Template personalData can only be set once", }); } diff --git a/packages/eservice-template-process/src/services/eserviceTemplateService.ts b/packages/eservice-template-process/src/services/eserviceTemplateService.ts index cdf00022b4..cce13bf077 100644 --- a/packages/eservice-template-process/src/services/eserviceTemplateService.ts +++ b/packages/eservice-template-process/src/services/eserviceTemplateService.ts @@ -50,7 +50,7 @@ import { notValidEServiceTemplateVersionState, attributeDuplicatedInGroup, missingPersonalDataFlag, - eserviceTemplatePersonalDataCanOnlyBeSetOnce, + eserviceTemplatePersonalDataFlagCanOnlyBeSetOnce, } from "../model/domain/errors.js"; import { versionAttributeGroupSupersetMissingInAttributesSeed, @@ -1816,7 +1816,9 @@ export function eserviceTemplateServiceBuilder( assertPublishedEServiceTemplate(eserviceTemplate.data); if (eserviceTemplate.data.personalData !== undefined) { - throw eserviceTemplatePersonalDataCanOnlyBeSetOnce(eserviceTemplateId); + throw eserviceTemplatePersonalDataFlagCanOnlyBeSetOnce( + eserviceTemplateId + ); } const updatedEServiceTemplate: EServiceTemplate = { diff --git a/packages/eservice-template-process/src/utilities/errorMappers.ts b/packages/eservice-template-process/src/utilities/errorMappers.ts index c989fafca0..ff99dce8c5 100644 --- a/packages/eservice-template-process/src/utilities/errorMappers.ts +++ b/packages/eservice-template-process/src/utilities/errorMappers.ts @@ -320,7 +320,7 @@ export const updateEServiceTemplatePersonalDataErrorMapper = ( .with("operationForbidden", () => HTTP_STATUS_FORBIDDEN) .with( "eserviceTemplateWithoutPublishedVersion", - "eserviceTemplatePersonalDataCanOnlyBeSetOnce", + "eserviceTemplatePersonalDataFlagCanOnlyBeSetOnce", () => HTTP_STATUS_CONFLICT ) .otherwise(() => HTTP_STATUS_INTERNAL_SERVER_ERROR); diff --git a/packages/eservice-template-process/test/api/updateEServiceTemplatePersonalDataFlag.test.ts b/packages/eservice-template-process/test/api/updateEServiceTemplatePersonalDataFlag.test.ts index 6d69aa1f14..1a47a673be 100644 --- a/packages/eservice-template-process/test/api/updateEServiceTemplatePersonalDataFlag.test.ts +++ b/packages/eservice-template-process/test/api/updateEServiceTemplatePersonalDataFlag.test.ts @@ -23,7 +23,7 @@ import { eserviceTemplateToApiEServiceTemplate } from "../../src/model/domain/ap import { eserviceTemplateNotFound, eserviceTemplateWithoutPublishedVersion, - eserviceTemplatePersonalDataCanOnlyBeSetOnce, + eserviceTemplatePersonalDataFlagCanOnlyBeSetOnce, } from "../../src/model/domain/errors.js"; describe("API /templates/{templateId}/personalDataFlag", () => { @@ -90,7 +90,7 @@ describe("API /templates/{templateId}/personalDataFlag", () => { expectedStatus: 409, }, { - error: eserviceTemplatePersonalDataCanOnlyBeSetOnce( + error: eserviceTemplatePersonalDataFlagCanOnlyBeSetOnce( mockEServiceTemplate.id ), expectedStatus: 409, diff --git a/packages/eservice-template-process/test/integration/updateEServiceTemplatePersonalDataUpdatedAfterPublish.test.ts b/packages/eservice-template-process/test/integration/updateEServiceTemplatePersonalDataUpdatedAfterPublish.test.ts index add3d4667c..3a98a15b4a 100644 --- a/packages/eservice-template-process/test/integration/updateEServiceTemplatePersonalDataUpdatedAfterPublish.test.ts +++ b/packages/eservice-template-process/test/integration/updateEServiceTemplatePersonalDataUpdatedAfterPublish.test.ts @@ -23,7 +23,7 @@ import { } from "../integrationUtils.js"; import { eserviceTemplateNotFound, - eserviceTemplatePersonalDataCanOnlyBeSetOnce, + eserviceTemplatePersonalDataFlagCanOnlyBeSetOnce, eserviceTemplateWithoutPublishedVersion, } from "../../src/model/domain/errors.js"; @@ -109,7 +109,7 @@ describe("update EService Template personalData flag for an already created ESer }) ) ).rejects.toThrowError( - eserviceTemplatePersonalDataCanOnlyBeSetOnce(eserviceTemplate.id) + eserviceTemplatePersonalDataFlagCanOnlyBeSetOnce(eserviceTemplate.id) ); } ); From 27df31048c35c6e831022fcf4a5bf8cab4049330 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Tue, 30 Sep 2025 11:34:10 +0200 Subject: [PATCH 131/180] Renaming --- packages/catalog-process/src/services/catalogService.ts | 2 +- packages/catalog-process/src/utilities/errorMappers.ts | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/catalog-process/src/services/catalogService.ts b/packages/catalog-process/src/services/catalogService.ts index 67e63d8c63..c93257c1ce 100644 --- a/packages/catalog-process/src/services/catalogService.ts +++ b/packages/catalog-process/src/services/catalogService.ts @@ -2939,7 +2939,7 @@ export function catalogServiceBuilder( const eservice = await retrieveEService(eserviceId, readModelService); if (eservice.data.personalData !== undefined) { - throw eservicePersonalDataCanOnlyBeSetOnce(eserviceId); + throw eservicePersonalDataFlagCanOnlyBeSetOnce(eserviceId); } const updatedEservice: EService = { diff --git a/packages/catalog-process/src/utilities/errorMappers.ts b/packages/catalog-process/src/utilities/errorMappers.ts index cce80f5be5..cc906ee680 100644 --- a/packages/catalog-process/src/utilities/errorMappers.ts +++ b/packages/catalog-process/src/utilities/errorMappers.ts @@ -561,7 +561,10 @@ export const updateTemplateInstancePersonalDataErrorMapper = ( ): number => match(error.code) .with("eServiceNotFound", () => HTTP_STATUS_NOT_FOUND) - .with("eservicePersonalDataCanOnlyBeSetOnce", () => HTTP_STATUS_CONFLICT) + .with( + "eservicePersonalDataFlagCanOnlyBeSetOnce", + () => HTTP_STATUS_CONFLICT + ) .otherwise(() => HTTP_STATUS_INTERNAL_SERVER_ERROR); export const updateTemplateInstanceDescriptorVoucherLifespanErrorMapper = ( From 26c39c676ad6f1c54c0cc6d75c69435be8dd1fbf Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Tue, 30 Sep 2025 11:42:41 +0200 Subject: [PATCH 132/180] Fix --- .../src/handlers/eservices/handleEserviceEvent.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/email-notification-dispatcher/src/handlers/eservices/handleEserviceEvent.ts b/packages/email-notification-dispatcher/src/handlers/eservices/handleEserviceEvent.ts index 79a316c569..9462ab7c72 100644 --- a/packages/email-notification-dispatcher/src/handlers/eservices/handleEserviceEvent.ts +++ b/packages/email-notification-dispatcher/src/handlers/eservices/handleEserviceEvent.ts @@ -70,7 +70,8 @@ export async function handleEServiceEvent( "EServiceDescriptorDocumentDeletedByTemplateUpdate", "EServiceDescriptorDocumentUpdatedByTemplateUpdate", "EServiceSignalHubEnabled", - "EServiceSignalHubDisabled" + "EServiceSignalHubDisabled", + "EServicePersonalDataFlagUpdatedAfterPublication" ), }, () => { From 191818432b3edbebfdaa5ebcd87f76e0023806a2 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Tue, 30 Sep 2025 11:55:39 +0200 Subject: [PATCH 133/180] Renaming --- packages/catalog-process/src/routers/EServiceRouter.ts | 4 ++-- packages/catalog-process/src/utilities/errorMappers.ts | 2 +- .../src/routers/EServiceTemplateRouter.ts | 4 ++-- .../eservice-template-process/src/utilities/errorMappers.ts | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/catalog-process/src/routers/EServiceRouter.ts b/packages/catalog-process/src/routers/EServiceRouter.ts index e0a215ec55..9a43a2b039 100644 --- a/packages/catalog-process/src/routers/EServiceRouter.ts +++ b/packages/catalog-process/src/routers/EServiceRouter.ts @@ -74,7 +74,7 @@ import { updateAgreementApprovalPolicyErrorMapper, updateEServiceSignalhubFlagErrorMapper, documentListErrorMapper, - updateEServicePersonalDataErrorMapper, + updateEServicePersonalDataFlagErrorMapper, updateTemplateInstancePersonalDataErrorMapper, } from "../utilities/errorMappers.js"; import { CatalogService } from "../services/catalogService.js"; @@ -1520,7 +1520,7 @@ const eservicesRouter = ( } catch (error) { const errorRes = makeApiProblem( error, - updateEServicePersonalDataErrorMapper, + updateEServicePersonalDataFlagErrorMapper, ctx ); return res.status(errorRes.status).send(errorRes); diff --git a/packages/catalog-process/src/utilities/errorMappers.ts b/packages/catalog-process/src/utilities/errorMappers.ts index cc906ee680..cab84f25b0 100644 --- a/packages/catalog-process/src/utilities/errorMappers.ts +++ b/packages/catalog-process/src/utilities/errorMappers.ts @@ -699,7 +699,7 @@ export const updateTemplateInstanceDescriptorErrorMapper = ( ) .otherwise(() => HTTP_STATUS_INTERNAL_SERVER_ERROR); -export const updateEServicePersonalDataErrorMapper = ( +export const updateEServicePersonalDataFlagErrorMapper = ( error: ApiError ): number => match(error.code) diff --git a/packages/eservice-template-process/src/routers/EServiceTemplateRouter.ts b/packages/eservice-template-process/src/routers/EServiceTemplateRouter.ts index ec9bb35eb6..387e61c191 100644 --- a/packages/eservice-template-process/src/routers/EServiceTemplateRouter.ts +++ b/packages/eservice-template-process/src/routers/EServiceTemplateRouter.ts @@ -40,7 +40,7 @@ import { updateDocumentErrorMapper, deleteDocumentErrorMapper, getEServiceTemplatesErrorMapper, - updateEServiceTemplatePersonalDataErrorMapper, + updateEServiceTemplatePersonalDataFlagErrorMapper, } from "../utilities/errorMappers.js"; import { eserviceTemplateToApiEServiceTemplate, @@ -725,7 +725,7 @@ const eserviceTemplatesRouter = ( } catch (error) { const errorRes = makeApiProblem( error, - updateEServiceTemplatePersonalDataErrorMapper, + updateEServiceTemplatePersonalDataFlagErrorMapper, ctx ); return res.status(errorRes.status).send(errorRes); diff --git a/packages/eservice-template-process/src/utilities/errorMappers.ts b/packages/eservice-template-process/src/utilities/errorMappers.ts index c989fafca0..f987e25814 100644 --- a/packages/eservice-template-process/src/utilities/errorMappers.ts +++ b/packages/eservice-template-process/src/utilities/errorMappers.ts @@ -312,7 +312,7 @@ export const getEServiceTemplatesErrorMapper = ( .with("eserviceTemplateNotFound", () => HTTP_STATUS_NOT_FOUND) .otherwise(() => HTTP_STATUS_INTERNAL_SERVER_ERROR); -export const updateEServiceTemplatePersonalDataErrorMapper = ( +export const updateEServiceTemplatePersonalDataFlagErrorMapper = ( error: ApiError ): number => match(error.code) From 598b642af9eda53229d0aeb59fe7ee604ce158a5 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Tue, 30 Sep 2025 12:05:15 +0200 Subject: [PATCH 134/180] Add missing event in email-notification-dispatcher --- .../src/handlers/eservices/handleEserviceEvent.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/email-notification-dispatcher/src/handlers/eservices/handleEserviceEvent.ts b/packages/email-notification-dispatcher/src/handlers/eservices/handleEserviceEvent.ts index 9462ab7c72..ecdb99affa 100644 --- a/packages/email-notification-dispatcher/src/handlers/eservices/handleEserviceEvent.ts +++ b/packages/email-notification-dispatcher/src/handlers/eservices/handleEserviceEvent.ts @@ -71,7 +71,8 @@ export async function handleEServiceEvent( "EServiceDescriptorDocumentUpdatedByTemplateUpdate", "EServiceSignalHubEnabled", "EServiceSignalHubDisabled", - "EServicePersonalDataFlagUpdatedAfterPublication" + "EServicePersonalDataFlagUpdatedAfterPublication", + "EServicePersonalDataFlagUpdatedByTemplateUpdate" ), }, () => { From 8a0d2d58b56ccc37c84be91d5ba9b4b665cec07b Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Tue, 30 Sep 2025 14:43:23 +0200 Subject: [PATCH 135/180] Improve test --- .../updateEServicePersonalDataFlagAfterPublication.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/catalog-process/test/integration/updateEServicePersonalDataFlagAfterPublication.test.ts b/packages/catalog-process/test/integration/updateEServicePersonalDataFlagAfterPublication.test.ts index 30220fc98f..e5c4c4811c 100644 --- a/packages/catalog-process/test/integration/updateEServicePersonalDataFlagAfterPublication.test.ts +++ b/packages/catalog-process/test/integration/updateEServicePersonalDataFlagAfterPublication.test.ts @@ -73,7 +73,7 @@ describe("update E-service personalData flag for an already created E-service", it.each([ [true, true], - [false, false], + [false, true], ])( "should NOT write on event-store for the update of the E-service personalData flag if it was already set (%s -> %s)", async (oldPersonalDataValue, newPersonalDataValue) => { From 4310e9a388bee44343482a03c90cf86226804147 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Tue, 30 Sep 2025 14:43:48 +0200 Subject: [PATCH 136/180] Add test --- ...teTemplateInstancePersonalDataFlag.test.ts | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 packages/catalog-process/test/integration/updateTemplateInstancePersonalDataFlag.test.ts diff --git a/packages/catalog-process/test/integration/updateTemplateInstancePersonalDataFlag.test.ts b/packages/catalog-process/test/integration/updateTemplateInstancePersonalDataFlag.test.ts new file mode 100644 index 0000000000..1115999315 --- /dev/null +++ b/packages/catalog-process/test/integration/updateTemplateInstancePersonalDataFlag.test.ts @@ -0,0 +1,104 @@ +/* eslint-disable @typescript-eslint/no-floating-promises */ +import { + decodeProtobufPayload, + getMockContext, + getMockAuthData, + getMockDocument, + getMockDescriptor, + getMockEService, +} from "pagopa-interop-commons-test"; +import { + Descriptor, + descriptorState, + EService, + toEServiceV2, + EServicePersonalDataFlagUpdatedByTemplateUpdateV2, +} from "pagopa-interop-models"; +import { expect, describe, it } from "vitest"; +import { + eServiceNotFound, + eservicePersonalDataFlagCanOnlyBeSetOnce, +} from "../../src/model/domain/errors.js"; +import { + addOneEService, + catalogService, + readLastEserviceEvent, +} from "../integrationUtils.js"; + +describe("internalUpdateTemplateInstancePersonalDataFlag", () => { + it("should write on event-store for the internal update of the eService personalData flag", async () => { + const descriptor: Descriptor = { + ...getMockDescriptor(descriptorState.published), + interface: getMockDocument(), + }; + const eservice: EService = { + ...getMockEService(), + descriptors: [descriptor], + }; + await addOneEService(eservice); + + const updatedPersonalDataFlag = true; + + await catalogService.internalUpdateTemplateInstancePersonalDataFlag( + eservice.id, + updatedPersonalDataFlag, + getMockContext({ authData: getMockAuthData(eservice.producerId) }) + ); + + const updatedEService: EService = { + ...eservice, + personalData: updatedPersonalDataFlag, + }; + + const writtenEvent = await readLastEserviceEvent(eservice.id); + expect(writtenEvent).toMatchObject({ + stream_id: eservice.id, + version: "1", + type: "EServicePersonalDataFlagUpdatedByTemplateUpdate", + event_version: 2, + }); + const writtenPayload = decodeProtobufPayload({ + messageType: EServicePersonalDataFlagUpdatedByTemplateUpdateV2, + payload: writtenEvent.data, + }); + + expect(writtenPayload.eservice).toEqual(toEServiceV2(updatedEService)); + }); + + it("should throw eServiceNotFound if the eservice doesn't exist", async () => { + const eservice = getMockEService(); + + expect( + catalogService.internalUpdateTemplateInstancePersonalDataFlag( + eservice.id, + true, + getMockContext({ authData: getMockAuthData(eservice.producerId) }) + ) + ).rejects.toThrowError(eServiceNotFound(eservice.id)); + }); + + it("should throw eservicePersonalDataFlagCanOnlyBeSetOnce if the personalData flag was already set", async () => { + const descriptor: Descriptor = { + ...getMockDescriptor(descriptorState.published), + interface: getMockDocument(), + }; + + const eservice: EService = { + ...getMockEService(), + descriptors: [descriptor], + personalData: true, + }; + + await addOneEService(eservice); + + await expect( + catalogService.updateEServicePersonalDataFlagAfterPublication( + eservice.id, + false, + getMockContext({ authData: getMockAuthData(eservice.producerId) }) + ) + ).rejects.toThrowError( + eservicePersonalDataFlagCanOnlyBeSetOnce(eservice.id) + ); + }); +}); From 90462dc42bf13b9bdc292f954bd1611ceec597ea Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Tue, 30 Sep 2025 14:57:38 +0200 Subject: [PATCH 137/180] Improve feature flag --- packages/catalog-process/src/routers/EServiceRouter.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/catalog-process/src/routers/EServiceRouter.ts b/packages/catalog-process/src/routers/EServiceRouter.ts index 1dd62ec33b..0ee21510b4 100644 --- a/packages/catalog-process/src/routers/EServiceRouter.ts +++ b/packages/catalog-process/src/routers/EServiceRouter.ts @@ -2,6 +2,7 @@ import { ZodiosEndpointDefinitions } from "@zodios/core"; import { ZodiosRouter } from "@zodios/express"; import { catalogApi } from "pagopa-interop-api-clients"; import { + assertFeatureFlagEnabled, authRole, ExpressContext, fromAppContext, @@ -1476,9 +1477,7 @@ const eservicesRouter = ( try { validateAuthorization(ctx, [ADMIN_ROLE, API_ROLE]); - if (config.featureFlagEservicePersonalData === false) { - return res.status(501); - } + assertFeatureFlagEnabled(config, "featureFlagEservicePersonalData"); const updatedEService = await catalogService.updateEServicePersonalDataFlagAfterPublication( From 16b00453045310e58743b2ccbf303cc625f3c8e3 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Tue, 30 Sep 2025 14:58:45 +0200 Subject: [PATCH 138/180] Improve feature flag --- .../src/routers/EServiceTemplateRouter.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/eservice-template-process/src/routers/EServiceTemplateRouter.ts b/packages/eservice-template-process/src/routers/EServiceTemplateRouter.ts index ec9bb35eb6..ccb4d2d405 100644 --- a/packages/eservice-template-process/src/routers/EServiceTemplateRouter.ts +++ b/packages/eservice-template-process/src/routers/EServiceTemplateRouter.ts @@ -7,6 +7,7 @@ import { fromAppContext, authRole, validateAuthorization, + assertFeatureFlagEnabled, } from "pagopa-interop-commons"; import { eserviceTemplateApi } from "pagopa-interop-api-clients"; import { @@ -704,9 +705,7 @@ const eserviceTemplatesRouter = ( try { validateAuthorization(ctx, [ADMIN_ROLE, API_ROLE]); - if (config.featureFlagEservicePersonalData === false) { - return res.status(501).send(); - } + assertFeatureFlagEnabled(config, "featureFlagEservicePersonalData"); const updatedEServiceTemplate = await eserviceTemplateService.updateEServiceTemplatePersonalDataFlagAfterPublication( From ed462b346d5ce37fc1edb2863102dbc049d68510 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Wed, 1 Oct 2025 10:17:14 +0200 Subject: [PATCH 139/180] Add api test --- ...teTemplateInstancePersonalDataFlag.test.ts | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 packages/catalog-process/test/api/updateTemplateInstancePersonalDataFlag.test.ts diff --git a/packages/catalog-process/test/api/updateTemplateInstancePersonalDataFlag.test.ts b/packages/catalog-process/test/api/updateTemplateInstancePersonalDataFlag.test.ts new file mode 100644 index 0000000000..14125437cb --- /dev/null +++ b/packages/catalog-process/test/api/updateTemplateInstancePersonalDataFlag.test.ts @@ -0,0 +1,77 @@ +/* eslint-disable @typescript-eslint/explicit-function-return-type */ +import { describe, it, expect, vi } from "vitest"; +import request from "supertest"; +import { EService, EServiceId, generateId } from "pagopa-interop-models"; +import { generateToken, getMockEService } from "pagopa-interop-commons-test"; +import { authRole } from "pagopa-interop-commons"; +import { catalogApi } from "pagopa-interop-api-clients"; +import { api, catalogService } from "../vitest.api.setup.js"; +import { eServiceNotFound } from "../../src/model/domain/errors.js"; + +describe("API /internal/templates/eservices/{eServiceId}/personalDataFlag/set authorization test", () => { + const mockEService: EService = getMockEService(); + + catalogService.internalUpdateTemplateInstancePersonalDataFlag = vi + .fn() + .mockResolvedValue({}); + + const mockEServicePersonalDataFlagUpdateSeed: catalogApi.EServicePersonalDataFlagUpdateSeed = + { + personalData: true, + }; + + const makeRequest = async ( + token: string, + eServiceId: EServiceId, + body: catalogApi.EServicePersonalDataFlagUpdateSeed = mockEServicePersonalDataFlagUpdateSeed + ) => + request(api) + .post(`/internal/templates/eservices/${eServiceId}/personalDataFlag/set`) + .set("Authorization", `Bearer ${token}`) + .set("X-Correlation-Id", generateId()) + .send(body); + + it("Should return 204 for user with role internal", async () => { + const token = generateToken(authRole.INTERNAL_ROLE); + const res = await makeRequest(token, mockEService.id); + expect(res.status).toBe(204); + }); + + it.each( + Object.values(authRole).filter((role) => role !== authRole.INTERNAL_ROLE) + )("Should return 403 for user with role %s", async (role) => { + const token = generateToken(role); + const res = await makeRequest(token, mockEService.id); + + expect(res.status).toBe(403); + }); + + it("Should return $expectedStatus for $error.code", async () => { + catalogService.internalUpdateTemplateInstancePersonalDataFlag = vi + .fn() + .mockRejectedValue(eServiceNotFound(mockEService.id)); + + const token = generateToken(authRole.INTERNAL_ROLE); + const res = await makeRequest(token, mockEService.id); + + expect(res.status).toBe(404); + }); + + it.each([ + [{}, mockEService.id], + [{ personalDataFlag: "123" }, mockEService.id], + [{ ...mockEServicePersonalDataFlagUpdateSeed }, "invalidId"], + ])( + "Should return 400 if passed invalid params: %s (eserviceId: %s)", + async (body, eServiceId) => { + const token = generateToken(authRole.INTERNAL_ROLE); + const res = await makeRequest( + token, + eServiceId as EServiceId, + body as catalogApi.EServicePersonalDataFlagUpdateSeed + ); + + expect(res.status).toBe(400); + } + ); +}); From 9ee167189ede84155b51fa52fc96baed21204099 Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Thu, 2 Oct 2025 10:51:41 +0200 Subject: [PATCH 140/180] chore(deps): bump @pagopa/interop-outbound-models to 1.6.9 --- .../agreement-outbound-writer/package.json | 4 +-- packages/catalog-outbound-writer/package.json | 4 +-- .../delegation-outbound-writer/package.json | 4 +-- .../package.json | 4 +-- packages/purpose-outbound-writer/package.json | 4 +-- packages/tenant-outbound-writer/package.json | 4 +-- pnpm-lock.yaml | 30 +++++++++---------- 7 files changed, 27 insertions(+), 27 deletions(-) diff --git a/packages/agreement-outbound-writer/package.json b/packages/agreement-outbound-writer/package.json index 0d47fffc21..b86028fe53 100644 --- a/packages/agreement-outbound-writer/package.json +++ b/packages/agreement-outbound-writer/package.json @@ -27,7 +27,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.8", + "@pagopa/interop-outbound-models": "1.6.9", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", @@ -38,4 +38,4 @@ "ts-pattern": "5.2.0", "zod": "3.23.8" } -} +} \ No newline at end of file diff --git a/packages/catalog-outbound-writer/package.json b/packages/catalog-outbound-writer/package.json index 0391c9c5da..90cfcee16e 100644 --- a/packages/catalog-outbound-writer/package.json +++ b/packages/catalog-outbound-writer/package.json @@ -27,7 +27,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.8", + "@pagopa/interop-outbound-models": "1.6.9", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", @@ -38,4 +38,4 @@ "ts-pattern": "5.2.0", "zod": "3.23.8" } -} +} \ No newline at end of file diff --git a/packages/delegation-outbound-writer/package.json b/packages/delegation-outbound-writer/package.json index a2f8ff2c41..62a47cbdfc 100644 --- a/packages/delegation-outbound-writer/package.json +++ b/packages/delegation-outbound-writer/package.json @@ -26,7 +26,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.8", + "@pagopa/interop-outbound-models": "1.6.9", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", @@ -37,4 +37,4 @@ "ts-pattern": "5.2.0", "zod": "3.23.8" } -} +} \ No newline at end of file diff --git a/packages/eservice-template-outbound-writer/package.json b/packages/eservice-template-outbound-writer/package.json index 936ad98797..740c2e94b6 100644 --- a/packages/eservice-template-outbound-writer/package.json +++ b/packages/eservice-template-outbound-writer/package.json @@ -26,7 +26,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.8", + "@pagopa/interop-outbound-models": "1.6.9", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", @@ -37,4 +37,4 @@ "ts-pattern": "5.2.0", "zod": "3.23.8" } -} +} \ No newline at end of file diff --git a/packages/purpose-outbound-writer/package.json b/packages/purpose-outbound-writer/package.json index 24152bb759..828fd0dda7 100644 --- a/packages/purpose-outbound-writer/package.json +++ b/packages/purpose-outbound-writer/package.json @@ -27,7 +27,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.8", + "@pagopa/interop-outbound-models": "1.6.9", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", @@ -38,4 +38,4 @@ "ts-pattern": "5.2.0", "zod": "3.23.8" } -} +} \ No newline at end of file diff --git a/packages/tenant-outbound-writer/package.json b/packages/tenant-outbound-writer/package.json index 93d992a83c..cfcc25887f 100644 --- a/packages/tenant-outbound-writer/package.json +++ b/packages/tenant-outbound-writer/package.json @@ -27,7 +27,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.8", + "@pagopa/interop-outbound-models": "1.6.9", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", @@ -38,4 +38,4 @@ "ts-pattern": "5.2.0", "zod": "3.23.8" } -} +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ec0e7ab5e2..5175e56f02 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -40,8 +40,8 @@ importers: packages/agreement-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.8 - version: 1.6.8 + specifier: 1.6.9 + version: 1.6.9 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -1184,8 +1184,8 @@ importers: packages/catalog-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.8 - version: 1.6.8 + specifier: 1.6.9 + version: 1.6.9 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -2118,8 +2118,8 @@ importers: packages/delegation-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.8 - version: 1.6.8 + specifier: 1.6.9 + version: 1.6.9 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -2776,8 +2776,8 @@ importers: packages/eservice-template-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.8 - version: 1.6.8 + specifier: 1.6.9 + version: 1.6.9 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -4535,8 +4535,8 @@ importers: packages/purpose-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.8 - version: 1.6.8 + specifier: 1.6.9 + version: 1.6.9 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -5234,8 +5234,8 @@ importers: packages/tenant-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.8 - version: 1.6.8 + specifier: 1.6.9 + version: 1.6.9 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -6944,8 +6944,8 @@ packages: '@pagopa/eslint-config@3.0.0': resolution: {integrity: sha512-eYIPdiuYRbRPR5k0OuteRNqYb0Z2nfJ/lZohejB7ylfBeSDWwkaV8Z19AXP4RymE6oEesyPDZ6i0yNaE9tQrHw==} - '@pagopa/interop-outbound-models@1.6.8': - resolution: {integrity: sha512-iy4lwWH1GmwpikG4j+J8JO29dhlT4yoSKcYXi101XsPm6AK/3+DS3Dvf6rddSGzLBBkqTM6sHjgqLTfjnGgsig==} + '@pagopa/interop-outbound-models@1.6.9': + resolution: {integrity: sha512-sptbwh98g2h7rw62QkikfHG4RfXPR4vKUO5UmuohVdEisdUv4EpSfIyxFjoptnNmKg0LxrIsLNHkQ+x5F8pdBw==} '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} @@ -13980,7 +13980,7 @@ snapshots: - tsutils - typescript - '@pagopa/interop-outbound-models@1.6.8': + '@pagopa/interop-outbound-models@1.6.9': dependencies: '@protobuf-ts/runtime': 2.9.4 ts-pattern: 5.2.0 From 37715bbca5c2bcd4e17c1efb58169b400699fc8b Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 2 Oct 2025 15:05:59 +0200 Subject: [PATCH 141/180] Upgrade outbound version --- .../agreement-outbound-writer/package.json | 2 +- packages/catalog-outbound-writer/package.json | 2 +- .../delegation-outbound-writer/package.json | 2 +- .../package.json | 2 +- packages/purpose-outbound-writer/package.json | 2 +- packages/tenant-outbound-writer/package.json | 2 +- pnpm-lock.yaml | 30 +++++++++---------- 7 files changed, 21 insertions(+), 21 deletions(-) diff --git a/packages/agreement-outbound-writer/package.json b/packages/agreement-outbound-writer/package.json index 72ee0c8d87..cf1e393bf1 100644 --- a/packages/agreement-outbound-writer/package.json +++ b/packages/agreement-outbound-writer/package.json @@ -27,7 +27,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.6", + "@pagopa/interop-outbound-models": "1.6.9", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/packages/catalog-outbound-writer/package.json b/packages/catalog-outbound-writer/package.json index 5d6ef34bed..5a093cda9d 100644 --- a/packages/catalog-outbound-writer/package.json +++ b/packages/catalog-outbound-writer/package.json @@ -27,7 +27,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.6", + "@pagopa/interop-outbound-models": "1.6.9", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/packages/delegation-outbound-writer/package.json b/packages/delegation-outbound-writer/package.json index f8800b56b6..1200c25816 100644 --- a/packages/delegation-outbound-writer/package.json +++ b/packages/delegation-outbound-writer/package.json @@ -26,7 +26,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.6", + "@pagopa/interop-outbound-models": "1.6.9", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/packages/eservice-template-outbound-writer/package.json b/packages/eservice-template-outbound-writer/package.json index 541a33e4e2..39e489da55 100644 --- a/packages/eservice-template-outbound-writer/package.json +++ b/packages/eservice-template-outbound-writer/package.json @@ -26,7 +26,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.6", + "@pagopa/interop-outbound-models": "1.6.9", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/packages/purpose-outbound-writer/package.json b/packages/purpose-outbound-writer/package.json index 944f17bdf9..d6a2809e23 100644 --- a/packages/purpose-outbound-writer/package.json +++ b/packages/purpose-outbound-writer/package.json @@ -27,7 +27,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.6", + "@pagopa/interop-outbound-models": "1.6.9", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/packages/tenant-outbound-writer/package.json b/packages/tenant-outbound-writer/package.json index c93e07a8a7..7caa68b9c1 100644 --- a/packages/tenant-outbound-writer/package.json +++ b/packages/tenant-outbound-writer/package.json @@ -27,7 +27,7 @@ "vitest": "1.6.1" }, "dependencies": { - "@pagopa/interop-outbound-models": "1.6.6", + "@pagopa/interop-outbound-models": "1.6.9", "@protobuf-ts/runtime": "2.9.4", "connection-string": "4.4.0", "dotenv-flow": "4.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f7791ddc7e..e121bfb72c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -40,8 +40,8 @@ importers: packages/agreement-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.6 - version: 1.6.6 + specifier: 1.6.9 + version: 1.6.9 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -1175,8 +1175,8 @@ importers: packages/catalog-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.6 - version: 1.6.6 + specifier: 1.6.9 + version: 1.6.9 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -2100,8 +2100,8 @@ importers: packages/delegation-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.6 - version: 1.6.6 + specifier: 1.6.9 + version: 1.6.9 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -2752,8 +2752,8 @@ importers: packages/eservice-template-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.6 - version: 1.6.6 + specifier: 1.6.9 + version: 1.6.9 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -4508,8 +4508,8 @@ importers: packages/purpose-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.6 - version: 1.6.6 + specifier: 1.6.9 + version: 1.6.9 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -5204,8 +5204,8 @@ importers: packages/tenant-outbound-writer: dependencies: '@pagopa/interop-outbound-models': - specifier: 1.6.6 - version: 1.6.6 + specifier: 1.6.9 + version: 1.6.9 '@protobuf-ts/runtime': specifier: 2.9.4 version: 2.9.4 @@ -6908,8 +6908,8 @@ packages: '@pagopa/eslint-config@3.0.0': resolution: {integrity: sha512-eYIPdiuYRbRPR5k0OuteRNqYb0Z2nfJ/lZohejB7ylfBeSDWwkaV8Z19AXP4RymE6oEesyPDZ6i0yNaE9tQrHw==} - '@pagopa/interop-outbound-models@1.6.6': - resolution: {integrity: sha512-TPoI/RPRl5wFH1ui6eK4KdAEC+gq4tN2svifSSBLQBdQB7FccxO1kYBs+0ytCRJp8u/T48EbsT+d9wyYvlwHfw==} + '@pagopa/interop-outbound-models@1.6.9': + resolution: {integrity: sha512-sptbwh98g2h7rw62QkikfHG4RfXPR4vKUO5UmuohVdEisdUv4EpSfIyxFjoptnNmKg0LxrIsLNHkQ+x5F8pdBw==} '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} @@ -13796,7 +13796,7 @@ snapshots: - tsutils - typescript - '@pagopa/interop-outbound-models@1.6.6': + '@pagopa/interop-outbound-models@1.6.9': dependencies: '@protobuf-ts/runtime': 2.9.4 ts-pattern: 5.2.0 From d02ef67f803d14279d9519cf139db6f2c8ffc413 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 2 Oct 2025 15:08:49 +0200 Subject: [PATCH 142/180] Refactor --- packages/catalog-process/src/services/catalogService.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/catalog-process/src/services/catalogService.ts b/packages/catalog-process/src/services/catalogService.ts index 31581bc5d0..770d678a8b 100644 --- a/packages/catalog-process/src/services/catalogService.ts +++ b/packages/catalog-process/src/services/catalogService.ts @@ -550,7 +550,7 @@ async function innerCreateEService( .with(true, () => seed.isClientAccessDelegable) .exhaustive(), templateId: template?.id, - ...(config.featureFlagEservicePersonalData + ...(isFeatureFlagEnabled(config, "featureFlagEservicePersonalData") ? { personalData: seed.personalData } : {}), }; @@ -4007,7 +4007,7 @@ async function updateDraftEService( .with(false, () => false) .with(true, () => updatedIsClientAccessDelegable) .exhaustive(), - ...(config.featureFlagEservicePersonalData + ...(isFeatureFlagEnabled(config, "featureFlagEservicePersonalData") ? { personalData: updatedPersonalData } : {}), }; From bba389897357e2bf01e2e8d575635fb201eb8090 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 2 Oct 2025 15:11:41 +0200 Subject: [PATCH 143/180] refactor --- packages/catalog-process/src/services/catalogService.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/catalog-process/src/services/catalogService.ts b/packages/catalog-process/src/services/catalogService.ts index 820baa29c1..f35339feab 100644 --- a/packages/catalog-process/src/services/catalogService.ts +++ b/packages/catalog-process/src/services/catalogService.ts @@ -553,7 +553,7 @@ async function innerCreateEService( .with(true, () => seed.isClientAccessDelegable) .exhaustive(), templateId: template?.id, - ...(config.featureFlagEservicePersonalData + ...(isFeatureFlagEnabled(config, "featureFlagEservicePersonalData") ? { personalData: seed.personalData } : {}), }; @@ -1632,7 +1632,7 @@ export function catalogServiceBuilder( } if ( - config.featureFlagEservicePersonalData && + isFeatureFlagEnabled(config, "featureFlagEservicePersonalData") && eservice.data.personalData === undefined ) { throw missingPersonalDataFlag(eserviceId, descriptorId); @@ -2721,7 +2721,7 @@ export function catalogServiceBuilder( } if ( - config.featureFlagEservicePersonalData && + isFeatureFlagEnabled(config, "featureFlagEservicePersonalData") && eservice.data.personalData === undefined ) { throw missingPersonalDataFlag(eserviceId, descriptorId); @@ -4066,7 +4066,7 @@ async function updateDraftEService( .with(false, () => false) .with(true, () => updatedIsClientAccessDelegable) .exhaustive(), - ...(config.featureFlagEservicePersonalData + ...(isFeatureFlagEnabled(config, "featureFlagEservicePersonalData") ? { personalData: updatedPersonalData } : {}), }; From 4684dc221aaf82c76040237ad765d5ca2051fc8f Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Fri, 3 Oct 2025 11:00:16 +0200 Subject: [PATCH 144/180] Fix patch --- packages/api-clients/open-api/catalogApi.yml | 1 + packages/catalog-process/src/services/catalogService.ts | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/api-clients/open-api/catalogApi.yml b/packages/api-clients/open-api/catalogApi.yml index 9e1d128ee7..df701880ac 100644 --- a/packages/api-clients/open-api/catalogApi.yml +++ b/packages/api-clients/open-api/catalogApi.yml @@ -2664,6 +2664,7 @@ components: type: boolean personalData: type: boolean + nullable: true UpdateEServiceTemplateInstanceSeed: type: object additionalProperties: false diff --git a/packages/catalog-process/src/services/catalogService.ts b/packages/catalog-process/src/services/catalogService.ts index 770d678a8b..d477e2dd9e 100644 --- a/packages/catalog-process/src/services/catalogService.ts +++ b/packages/catalog-process/src/services/catalogService.ts @@ -3975,7 +3975,11 @@ async function updateDraftEService( const updatedPersonalData = match(type) .with("put", () => personalData) - .with("patch", () => personalData ?? eservice.data.personalData) + .with("patch", () => + personalData ?? personalData === null + ? undefined + : eservice.data.personalData + ) .exhaustive(); const updatedEService: EService = { From e562fb6492e71c6a54031707ee51199b884ffda6 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Fri, 3 Oct 2025 11:10:36 +0200 Subject: [PATCH 145/180] Fix --- .../src/services/catalogService.ts | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/packages/catalog-process/src/services/catalogService.ts b/packages/catalog-process/src/services/catalogService.ts index d477e2dd9e..babbd3c381 100644 --- a/packages/catalog-process/src/services/catalogService.ts +++ b/packages/catalog-process/src/services/catalogService.ts @@ -3867,12 +3867,10 @@ async function extractEServiceRiskAnalysisFromTemplate( return riskAnalysis; } +// eslint-disable-next-line sonarjs/cognitive-complexity async function updateDraftEService( eserviceId: EServiceId, - { - seed, - type, - }: + typeAndSeed: | { type: "put"; seed: catalogApi.UpdateEServiceSeed; @@ -3909,11 +3907,7 @@ async function updateDraftEService( isSignalHubEnabled, isConsumerDelegable, isClientAccessDelegable, - personalData, - ...rest - } = seed; - void (rest satisfies Record); - // ^ To make sure we extract all the updated fields + } = typeAndSeed.seed; if (name && name !== eservice.data.name) { await assertEServiceNameAvailableForProducer( @@ -3952,12 +3946,12 @@ async function updateDraftEService( const checkedRiskAnalysis = updatedMode === eserviceMode.receive ? eservice.data.riskAnalysis : []; - const updatedIsSignalHubEnabled = match(type) + const updatedIsSignalHubEnabled = match(typeAndSeed.type) .with("put", () => isSignalHubEnabled) .with("patch", () => isSignalHubEnabled ?? eservice.data.isSignalHubEnabled) .exhaustive(); - const updatedIsConsumerDelegable = match(type) + const updatedIsConsumerDelegable = match(typeAndSeed.type) .with("put", () => isConsumerDelegable) .with( "patch", @@ -3965,7 +3959,7 @@ async function updateDraftEService( ) .exhaustive(); - const updatedIsClientAccessDelegable = match(type) + const updatedIsClientAccessDelegable = match(typeAndSeed.type) .with("put", () => isClientAccessDelegable) .with( "patch", @@ -3973,10 +3967,10 @@ async function updateDraftEService( ) .exhaustive(); - const updatedPersonalData = match(type) - .with("put", () => personalData) - .with("patch", () => - personalData ?? personalData === null + const updatedPersonalData = match(typeAndSeed) + .with({ type: "put" }, ({ seed }) => seed.personalData) + .with({ type: "patch" }, ({ seed }) => + seed.personalData ?? seed.personalData === null ? undefined : eservice.data.personalData ) From d166cb8e7ffe552be78b9cb8fee5298be1be4af3 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 6 Oct 2025 10:48:42 +0200 Subject: [PATCH 146/180] Update endpoint --- packages/api-clients/open-api/catalogApi.yml | 2 +- packages/catalog-process/src/routers/EServiceRouter.ts | 2 +- .../test/api/updateTemplateInstancePersonalDataFlag.test.ts | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/api-clients/open-api/catalogApi.yml b/packages/api-clients/open-api/catalogApi.yml index 828743eff0..c4543f7f77 100644 --- a/packages/api-clients/open-api/catalogApi.yml +++ b/packages/api-clients/open-api/catalogApi.yml @@ -2277,7 +2277,7 @@ paths: application/problem+json: schema: $ref: "#/components/schemas/Problem" - /internal/templates/eservices/{eServiceId}/personalDataFlag/set: + /internal/templates/eservices/{eServiceId}/personalDataFlag: post: parameters: - $ref: "#/components/parameters/CorrelationIdHeader" diff --git a/packages/catalog-process/src/routers/EServiceRouter.ts b/packages/catalog-process/src/routers/EServiceRouter.ts index aff901934f..6ba5f4803b 100644 --- a/packages/catalog-process/src/routers/EServiceRouter.ts +++ b/packages/catalog-process/src/routers/EServiceRouter.ts @@ -1237,7 +1237,7 @@ const eservicesRouter = ( } ) .post( - "/internal/templates/eservices/:eServiceId/personalDataFlag/set", + "/internal/templates/eservices/:eServiceId/personalDataFlag", async (req, res) => { const ctx = fromAppContext(req.ctx); diff --git a/packages/catalog-process/test/api/updateTemplateInstancePersonalDataFlag.test.ts b/packages/catalog-process/test/api/updateTemplateInstancePersonalDataFlag.test.ts index 14125437cb..1c8a634bb4 100644 --- a/packages/catalog-process/test/api/updateTemplateInstancePersonalDataFlag.test.ts +++ b/packages/catalog-process/test/api/updateTemplateInstancePersonalDataFlag.test.ts @@ -8,7 +8,7 @@ import { catalogApi } from "pagopa-interop-api-clients"; import { api, catalogService } from "../vitest.api.setup.js"; import { eServiceNotFound } from "../../src/model/domain/errors.js"; -describe("API /internal/templates/eservices/{eServiceId}/personalDataFlag/set authorization test", () => { +describe("API /internal/templates/eservices/{eServiceId}/personalDataFlag authorization test", () => { const mockEService: EService = getMockEService(); catalogService.internalUpdateTemplateInstancePersonalDataFlag = vi @@ -26,7 +26,7 @@ describe("API /internal/templates/eservices/{eServiceId}/personalDataFlag/set au body: catalogApi.EServicePersonalDataFlagUpdateSeed = mockEServicePersonalDataFlagUpdateSeed ) => request(api) - .post(`/internal/templates/eservices/${eServiceId}/personalDataFlag/set`) + .post(`/internal/templates/eservices/${eServiceId}/personalDataFlag`) .set("Authorization", `Bearer ${token}`) .set("X-Correlation-Id", generateId()) .send(body); From 130999ba0a4fb866ad4d0fe864c2445538c40513 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 6 Oct 2025 12:51:59 +0200 Subject: [PATCH 147/180] Fix --- packages/catalog-process/src/services/catalogService.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/catalog-process/src/services/catalogService.ts b/packages/catalog-process/src/services/catalogService.ts index babbd3c381..e88a4a5890 100644 --- a/packages/catalog-process/src/services/catalogService.ts +++ b/packages/catalog-process/src/services/catalogService.ts @@ -3969,10 +3969,11 @@ async function updateDraftEService( const updatedPersonalData = match(typeAndSeed) .with({ type: "put" }, ({ seed }) => seed.personalData) - .with({ type: "patch" }, ({ seed }) => - seed.personalData ?? seed.personalData === null - ? undefined - : eservice.data.personalData + .with( + { type: "patch" }, + ({ seed }) => + seed.personalData ?? + (seed.personalData === null ? undefined : eservice.data.personalData) ) .exhaustive(); From d070cd14f19c7e63837e7579c6e305767245737c Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 6 Oct 2025 15:48:01 +0200 Subject: [PATCH 148/180] Update risk analysis validation with personalData --- .../src/services/catalogService.ts | 6 +++-- .../src/services/validators.ts | 9 ++++--- .../risk-analysis/riskAnalysisValidation.ts | 7 ++++- .../src/services/eserviceTemplateService.ts | 12 ++++++--- .../src/services/validators.ts | 3 ++- .../src/services/purposeService.ts | 26 ++++++++++++++----- .../src/services/validators.ts | 15 ++++++++--- 7 files changed, 56 insertions(+), 22 deletions(-) diff --git a/packages/catalog-process/src/services/catalogService.ts b/packages/catalog-process/src/services/catalogService.ts index c93257c1ce..10494a4076 100644 --- a/packages/catalog-process/src/services/catalogService.ts +++ b/packages/catalog-process/src/services/catalogService.ts @@ -2199,8 +2199,9 @@ export function catalogServiceBuilder( const validatedRiskAnalysisForm = validateRiskAnalysisSchemaOrThrow( eserviceRiskAnalysisSeed.riskAnalysisForm, tenant.kind, - new Date() // [todo remove comment] risk analysis creation + new Date(), // [todo remove comment] risk analysis creation // drawback: the date of the risk analysis is set below in the function riskAnalysisValidatedFormToNewRiskAnalysis + eservice.data.personalData ); const newRiskAnalysis: RiskAnalysis = @@ -2285,8 +2286,9 @@ export function catalogServiceBuilder( const validatedRiskAnalysisForm = validateRiskAnalysisSchemaOrThrow( eserviceRiskAnalysisSeed.riskAnalysisForm, tenant.kind, - new Date() // [todo remove comment] risk analysis update + new Date(), // [todo remove comment] risk analysis update // drawback: the date of the risk analysis is replaced below in the function riskAnalysisValidatedFormToNewRiskAnalysis + eservice.data.personalData ); const updatedRiskAnalysis: RiskAnalysis = { diff --git a/packages/catalog-process/src/services/validators.ts b/packages/catalog-process/src/services/validators.ts index 331cab32d0..2980ee7b10 100644 --- a/packages/catalog-process/src/services/validators.ts +++ b/packages/catalog-process/src/services/validators.ts @@ -203,13 +203,15 @@ export function assertHasNoDraftOrWaitingForApprovalDescriptor( export function validateRiskAnalysisSchemaOrThrow( riskAnalysisForm: catalogApi.EServiceRiskAnalysisSeed["riskAnalysisForm"], tenantKind: TenantKind, - dateForExpirationValidation: Date + dateForExpirationValidation: Date, + personalDataInEService: boolean | undefined ): RiskAnalysisValidatedForm { const result = validateRiskAnalysis( riskAnalysisForm, true, tenantKind, - dateForExpirationValidation + dateForExpirationValidation, + personalDataInEService ); if (result.type === "invalid") { throw riskAnalysisValidationFailed(result.issues); @@ -233,7 +235,8 @@ export function assertRiskAnalysisIsValidForPublication( ), false, tenantKind, - new Date() + new Date(), + eservice.personalData ); if (result.type === "invalid") { diff --git a/packages/commons/src/risk-analysis/riskAnalysisValidation.ts b/packages/commons/src/risk-analysis/riskAnalysisValidation.ts index 1e895292b2..718531f24b 100644 --- a/packages/commons/src/risk-analysis/riskAnalysisValidation.ts +++ b/packages/commons/src/risk-analysis/riskAnalysisValidation.ts @@ -31,7 +31,8 @@ export function validateRiskAnalysis( riskAnalysisForm: RiskAnalysisFormToValidate, schemaOnlyValidation: boolean, tenantKind: TenantKind, - dateForExpirationValidation: Date + dateForExpirationValidation: Date, + personalDataInEService: boolean | undefined ): RiskAnalysisValidationResult { const formRulesForValidation = getFormRulesByVersion( tenantKind, @@ -92,6 +93,10 @@ export function validateRiskAnalysis( } ); + if (riskAnalysisForm.version === "3.1") { + console.log("TODO add actual check", personalDataInEService); + } + return validResult({ version: formRulesForValidation.version, singleAnswers, diff --git a/packages/eservice-template-process/src/services/eserviceTemplateService.ts b/packages/eservice-template-process/src/services/eserviceTemplateService.ts index cce13bf077..e1f0358496 100644 --- a/packages/eservice-template-process/src/services/eserviceTemplateService.ts +++ b/packages/eservice-template-process/src/services/eserviceTemplateService.ts @@ -246,13 +246,15 @@ const replaceEServiceTemplateVersion = ( export function validateRiskAnalysisSchemaOrThrow( riskAnalysisForm: eserviceTemplateApi.EServiceTemplateRiskAnalysisSeed["riskAnalysisForm"], tenantKind: TenantKind, - dateForExpirationValidation: Date + dateForExpirationValidation: Date, + personalDataInEService: boolean | undefined ): RiskAnalysisValidatedForm { const result = validateRiskAnalysis( riskAnalysisForm, true, tenantKind, - dateForExpirationValidation + dateForExpirationValidation, + personalDataInEService ); if (result.type === "invalid") { throw riskAnalysisValidationFailed(result.issues); @@ -921,7 +923,8 @@ export function eserviceTemplateServiceBuilder( const validatedRiskAnalysisForm = validateRiskAnalysisSchemaOrThrow( createRiskAnalysis.riskAnalysisForm, createRiskAnalysis.tenantKind, - new Date() + new Date(), + template.data.personalData ); const newRiskAnalysis: EServiceTemplateRiskAnalysis = @@ -1007,7 +1010,8 @@ export function eserviceTemplateServiceBuilder( const validatedForm = validateRiskAnalysisSchemaOrThrow( updateRiskAnalysisSeed.riskAnalysisForm, updateRiskAnalysisSeed.tenantKind, - new Date() + new Date(), + template.data.personalData ); const updatedRiskAnalysisForm: RiskAnalysisForm = { diff --git a/packages/eservice-template-process/src/services/validators.ts b/packages/eservice-template-process/src/services/validators.ts index fc78063c55..eba104606f 100644 --- a/packages/eservice-template-process/src/services/validators.ts +++ b/packages/eservice-template-process/src/services/validators.ts @@ -164,7 +164,8 @@ export function assertRiskAnalysisIsValidForPublication( ), false, riskAnalysis.tenantKind, - new Date() + new Date(), + eserviceTemplate.personalData ); if (result.type === "invalid") { diff --git a/packages/purpose-process/src/services/purposeService.ts b/packages/purpose-process/src/services/purposeService.ts index 7471401a18..7ca60759e2 100644 --- a/packages/purpose-process/src/services/purposeService.ts +++ b/packages/purpose-process/src/services/purposeService.ts @@ -289,7 +289,8 @@ export function purposeServiceBuilder( purpose.data.riskAnalysisForm, false, tenantKind, - purpose.data.createdAt + purpose.data.createdAt, + eservice.personalData ) : true; @@ -850,7 +851,8 @@ export function purposeServiceBuilder( purpose.data.riskAnalysisForm, false, tenantKind, - new Date() + new Date(), + eservice.personalData ) : true; @@ -1004,6 +1006,7 @@ export function purposeServiceBuilder( schemaOnlyValidation: false, tenantKind, dateForExpirationValidation: new Date(), // beware: if the purpose version was waiting for approval, a new RA might have been published + personalDataInEService: eservice.personalData, }); } @@ -1237,11 +1240,13 @@ export function purposeServiceBuilder( const createdAt = new Date(); + const eservice = await retrieveEService(eserviceId, readModelService); const validatedFormSeed = validateAndTransformRiskAnalysis( purposeSeed.riskAnalysisForm, false, await retrieveTenantKind(authData.organizationId, readModelService), - createdAt + createdAt, + eservice.personalData ); await retrieveActiveAgreement(eserviceId, consumerId, readModelService); @@ -1341,6 +1346,7 @@ export function purposeServiceBuilder( schemaOnlyValidation: false, tenantKind: producerKind, dateForExpirationValidation: createdAt, + personalDataInEService: eservice.personalData, }); const newVersion: PurposeVersion = { @@ -1453,9 +1459,10 @@ export function purposeServiceBuilder( ? `${title}${suffix}` : `${title.slice(0, prefixLengthAllowance)}${dots}${suffix}`; + const eserviceId = unsafeBrandId(seed.eserviceId); await assertPurposeTitleIsNotDuplicated({ readModelService, - eserviceId: unsafeBrandId(seed.eserviceId), + eserviceId, consumerId: organizationId, title: clonedPurposeTitle, }); @@ -1474,6 +1481,8 @@ export function purposeServiceBuilder( delegationId: purposeToClone.data.delegationId, }; + const eservice = await retrieveEService(eserviceId, readModelService); + const isRiskAnalysisValid = clonedRiskAnalysisForm ? validateRiskAnalysis( riskAnalysisFormToRiskAnalysisFormToValidate( @@ -1481,7 +1490,8 @@ export function purposeServiceBuilder( ), false, tenantKind, - currentDate + currentDate, + eservice.personalData ).type === "valid" : false; @@ -1680,7 +1690,8 @@ const performUpdatePurpose = async ( riskAnalysisForm, true, tenantKind, - new Date() + new Date(), + eservice.personalData ) : purpose.data.riskAnalysisForm; @@ -1724,7 +1735,8 @@ const performUpdatePurpose = async ( updatedPurpose.riskAnalysisForm, false, tenantKind, - new Date() + new Date(), + eservice.personalData ), }, metadata: { version: createdEvent.newVersion }, diff --git a/packages/purpose-process/src/services/validators.ts b/packages/purpose-process/src/services/validators.ts index 5b1b03cf00..bcc34cd8cc 100644 --- a/packages/purpose-process/src/services/validators.ts +++ b/packages/purpose-process/src/services/validators.ts @@ -50,7 +50,8 @@ export const isRiskAnalysisFormValid = ( riskAnalysisForm: RiskAnalysisForm | undefined, schemaOnlyValidation: boolean, tenantKind: TenantKind, - dateForExpirationValidation: Date + dateForExpirationValidation: Date, + personalDataInEService: boolean | undefined ): boolean => { if (riskAnalysisForm === undefined) { return false; @@ -60,7 +61,8 @@ export const isRiskAnalysisFormValid = ( riskAnalysisFormToRiskAnalysisFormToValidate(riskAnalysisForm), schemaOnlyValidation, tenantKind, - dateForExpirationValidation + dateForExpirationValidation, + personalDataInEService ).type === "valid" ); } @@ -117,17 +119,20 @@ export function validateRiskAnalysisOrThrow({ schemaOnlyValidation, tenantKind, dateForExpirationValidation, + personalDataInEService, }: { riskAnalysisForm: purposeApi.RiskAnalysisFormSeed; schemaOnlyValidation: boolean; tenantKind: TenantKind; dateForExpirationValidation: Date; + personalDataInEService: boolean | undefined; }): RiskAnalysisValidatedForm { const result = validateRiskAnalysis( riskAnalysisForm, schemaOnlyValidation, tenantKind, - dateForExpirationValidation + dateForExpirationValidation, + personalDataInEService ); return match(result) .with({ type: "invalid" }, ({ issues }) => { @@ -141,7 +146,8 @@ export function validateAndTransformRiskAnalysis( riskAnalysisForm: purposeApi.RiskAnalysisFormSeed | undefined, schemaOnlyValidation: boolean, tenantKind: TenantKind, - dateForExpirationValidation: Date + dateForExpirationValidation: Date, + personalDataInEService: boolean | undefined ): PurposeRiskAnalysisForm | undefined { if (!riskAnalysisForm) { return undefined; @@ -151,6 +157,7 @@ export function validateAndTransformRiskAnalysis( schemaOnlyValidation, tenantKind, dateForExpirationValidation, + personalDataInEService, }); return { From e18a2d97c301ce7840ffb1fdd586a665ecdcb993 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 6 Oct 2025 15:51:46 +0200 Subject: [PATCH 149/180] Fix merge --- .../src/handlers/handleEServiceEvent.ts | 6 +++--- packages/models/src/m2m-event/eserviceM2MEvent.ts | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/m2m-event-dispatcher/src/handlers/handleEServiceEvent.ts b/packages/m2m-event-dispatcher/src/handlers/handleEServiceEvent.ts index 1d0d142b32..673e4f6aba 100644 --- a/packages/m2m-event-dispatcher/src/handlers/handleEServiceEvent.ts +++ b/packages/m2m-event-dispatcher/src/handlers/handleEServiceEvent.ts @@ -44,7 +44,8 @@ export async function handleEServiceEvent( "EServiceSignalHubDisabled", "EServiceRiskAnalysisAdded", "EServiceRiskAnalysisUpdated", - "EServiceRiskAnalysisDeleted" + "EServiceRiskAnalysisDeleted", + "EServicePersonalDataFlagUpdatedAfterPublication" ), }, async (event) => { @@ -91,8 +92,7 @@ export async function handleEServiceEvent( "EServiceDescriptorDocumentUpdatedByTemplateUpdate", "EServiceDescriptorInterfaceAdded", "EServiceDescriptorInterfaceUpdated", - "EServiceDescriptorInterfaceDeleted", - "EServicePersonalDataFlagUpdatedAfterPublication" + "EServiceDescriptorInterfaceDeleted" ), }, async (event) => { diff --git a/packages/models/src/m2m-event/eserviceM2MEvent.ts b/packages/models/src/m2m-event/eserviceM2MEvent.ts index 3898aa60ed..c66e97c513 100644 --- a/packages/models/src/m2m-event/eserviceM2MEvent.ts +++ b/packages/models/src/m2m-event/eserviceM2MEvent.ts @@ -31,6 +31,7 @@ export const EServiceM2MEventType = z.enum([ "EServiceRiskAnalysisAdded", "EServiceRiskAnalysisUpdated", "EServiceRiskAnalysisDeleted", + "EServicePersonalDataFlagUpdatedAfterPublication", // EService Descriptor events "EServiceDescriptorPublished", From d50c1b58cd172244c31319b29f0d0969103942ac Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 6 Oct 2025 16:04:04 +0200 Subject: [PATCH 150/180] Fix merge --- .../src/services/event-builders/eserviceM2MEventBuilder.ts | 3 ++- .../src/model/eserviceM2MEventApiConverter.ts | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/m2m-event-dispatcher/src/services/event-builders/eserviceM2MEventBuilder.ts b/packages/m2m-event-dispatcher/src/services/event-builders/eserviceM2MEventBuilder.ts index 3252dfebec..c15baf16a5 100644 --- a/packages/m2m-event-dispatcher/src/services/event-builders/eserviceM2MEventBuilder.ts +++ b/packages/m2m-event-dispatcher/src/services/event-builders/eserviceM2MEventBuilder.ts @@ -120,7 +120,8 @@ function getEServiceM2MEventVisibility( "EServiceDescriptorArchived", "EServiceDescriptorQuotasUpdated", "EServiceDescriptorAgreementApprovalPolicyUpdated", - "EServiceDescriptorAttributesUpdated" + "EServiceDescriptorAttributesUpdated", + "EServicePersonalDataFlagUpdatedAfterPublication" ), () => m2mEventVisibility.public ) diff --git a/packages/m2m-event-manager/src/model/eserviceM2MEventApiConverter.ts b/packages/m2m-event-manager/src/model/eserviceM2MEventApiConverter.ts index cee1bf0647..9108e2a2ed 100644 --- a/packages/m2m-event-manager/src/model/eserviceM2MEventApiConverter.ts +++ b/packages/m2m-event-manager/src/model/eserviceM2MEventApiConverter.ts @@ -124,6 +124,10 @@ function toApiEServiceM2MEventType( "EServiceDescriptorInterfaceDeleted", () => "ESERVICE_DESCRIPTOR_INTERFACE_DELETED" ) + .with( + "EServicePersonalDataFlagUpdatedAfterPublication", + () => "ESERVICE_PERSONAL_DATA_UPDATED_AFTER_PUBLICATION" + ) .exhaustive(); } From cd01499738abf8cdc4da58e1f73bd4ffb58073e6 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 6 Oct 2025 16:15:40 +0200 Subject: [PATCH 151/180] Fix merge --- .../src/model/eserviceM2MEventApiConverter.ts | 4 ++++ packages/models/src/m2m-event/eserviceM2MEvent.ts | 1 + 2 files changed, 5 insertions(+) diff --git a/packages/m2m-event-manager/src/model/eserviceM2MEventApiConverter.ts b/packages/m2m-event-manager/src/model/eserviceM2MEventApiConverter.ts index 9108e2a2ed..d9b8ccd17a 100644 --- a/packages/m2m-event-manager/src/model/eserviceM2MEventApiConverter.ts +++ b/packages/m2m-event-manager/src/model/eserviceM2MEventApiConverter.ts @@ -128,6 +128,10 @@ function toApiEServiceM2MEventType( "EServicePersonalDataFlagUpdatedAfterPublication", () => "ESERVICE_PERSONAL_DATA_UPDATED_AFTER_PUBLICATION" ) + .with( + "EServicePersonalDataFlagUpdatedByTemplateUpdate", + () => "ESERVICE_PERSONAL_DATA_UPDATED_BY_TEMPLATE_UPDATE" + ) .exhaustive(); } diff --git a/packages/models/src/m2m-event/eserviceM2MEvent.ts b/packages/models/src/m2m-event/eserviceM2MEvent.ts index c66e97c513..1b4ad10835 100644 --- a/packages/models/src/m2m-event/eserviceM2MEvent.ts +++ b/packages/models/src/m2m-event/eserviceM2MEvent.ts @@ -32,6 +32,7 @@ export const EServiceM2MEventType = z.enum([ "EServiceRiskAnalysisUpdated", "EServiceRiskAnalysisDeleted", "EServicePersonalDataFlagUpdatedAfterPublication", + "EServicePersonalDataFlagUpdatedByTemplateUpdate", // EService Descriptor events "EServiceDescriptorPublished", From e10429951faa3703581abb4dd24638fda7fff6f2 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 6 Oct 2025 16:18:38 +0200 Subject: [PATCH 152/180] Fix merge --- packages/m2m-event-dispatcher/test/handleEServiceEvent.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/m2m-event-dispatcher/test/handleEServiceEvent.test.ts b/packages/m2m-event-dispatcher/test/handleEServiceEvent.test.ts index ca7c40e0e8..4f2b2c3dc1 100644 --- a/packages/m2m-event-dispatcher/test/handleEServiceEvent.test.ts +++ b/packages/m2m-event-dispatcher/test/handleEServiceEvent.test.ts @@ -135,7 +135,8 @@ describe("handleEServiceEvent test", async () => { "EServiceIsClientAccessDelegableEnabled", "EServiceIsClientAccessDelegableDisabled", "EServiceSignalHubEnabled", - "EServiceSignalHubDisabled" + "EServiceSignalHubDisabled", + "EServicePersonalDataFlagUpdatedAfterPublication" ), async () => [ { From 634098337e6240b5eb7a896155f9b2d6f620642a Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 6 Oct 2025 16:31:14 +0200 Subject: [PATCH 153/180] Fix test --- .../m2m-event-manager/src/model/eserviceM2MEventApiConverter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/m2m-event-manager/src/model/eserviceM2MEventApiConverter.ts b/packages/m2m-event-manager/src/model/eserviceM2MEventApiConverter.ts index 9108e2a2ed..1ad80d29e1 100644 --- a/packages/m2m-event-manager/src/model/eserviceM2MEventApiConverter.ts +++ b/packages/m2m-event-manager/src/model/eserviceM2MEventApiConverter.ts @@ -126,7 +126,7 @@ function toApiEServiceM2MEventType( ) .with( "EServicePersonalDataFlagUpdatedAfterPublication", - () => "ESERVICE_PERSONAL_DATA_UPDATED_AFTER_PUBLICATION" + () => "ESERVICE_PERSONAL_DATA_FLAG_UPDATED_AFTER_PUBLICATION" ) .exhaustive(); } From 4760833ee3d2625f55b2492037ccf7252e7dce58 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 6 Oct 2025 16:37:55 +0200 Subject: [PATCH 154/180] Fix --- .../m2m-event-manager/src/model/eserviceM2MEventApiConverter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/m2m-event-manager/src/model/eserviceM2MEventApiConverter.ts b/packages/m2m-event-manager/src/model/eserviceM2MEventApiConverter.ts index 6ba64f05d6..88ee057722 100644 --- a/packages/m2m-event-manager/src/model/eserviceM2MEventApiConverter.ts +++ b/packages/m2m-event-manager/src/model/eserviceM2MEventApiConverter.ts @@ -130,7 +130,7 @@ function toApiEServiceM2MEventType( ) .with( "EServicePersonalDataFlagUpdatedByTemplateUpdate", - () => "ESERVICE_PERSONAL_DATA_UPDATED_BY_TEMPLATE_UPDATE" + () => "ESERVICE_PERSONAL_DATA_FLAG_UPDATED_BY_TEMPLATE_UPDATE" ) .exhaustive(); } From c9cbb59476475b165d8c6161a9395f70ba322164 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 6 Oct 2025 16:45:41 +0200 Subject: [PATCH 155/180] Fix --- .../handlers/eserviceTemplates/handleEserviceTemplatesEvent.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/in-app-notification-dispatcher/src/handlers/eserviceTemplates/handleEserviceTemplatesEvent.ts b/packages/in-app-notification-dispatcher/src/handlers/eserviceTemplates/handleEserviceTemplatesEvent.ts index 5d4d51930c..88b190f121 100644 --- a/packages/in-app-notification-dispatcher/src/handlers/eserviceTemplates/handleEserviceTemplatesEvent.ts +++ b/packages/in-app-notification-dispatcher/src/handlers/eserviceTemplates/handleEserviceTemplatesEvent.ts @@ -79,7 +79,8 @@ export async function handleEServiceTemplateEvent( "EServiceTemplateVersionQuotasUpdated", "EServiceTemplateVersionAdded", "EServiceTemplateVersionAttributesUpdated", - "EServiceTemplateVersionActivated" + "EServiceTemplateVersionActivated", + "EServiceTemplatePersonalDataFlagUpdatedAfterPublication" ), }, () => { From 0eb43226e6736e9da1f24c285d4077ab861449d8 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 6 Oct 2025 17:40:31 +0200 Subject: [PATCH 156/180] Fix --- .../m2m-event-dispatcher/src/handlers/handleEServiceEvent.ts | 1 + .../src/services/event-builders/eserviceM2MEventBuilder.ts | 3 ++- packages/m2m-event-dispatcher/test/handleEServiceEvent.test.ts | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/m2m-event-dispatcher/src/handlers/handleEServiceEvent.ts b/packages/m2m-event-dispatcher/src/handlers/handleEServiceEvent.ts index 90bb05a5f7..33d0be5dda 100644 --- a/packages/m2m-event-dispatcher/src/handlers/handleEServiceEvent.ts +++ b/packages/m2m-event-dispatcher/src/handlers/handleEServiceEvent.ts @@ -93,6 +93,7 @@ export async function handleEServiceEvent( "EServiceDescriptorDocumentUpdatedByTemplateUpdate", "EServiceDescriptorInterfaceAdded", "EServiceDescriptorInterfaceUpdated", + "EServiceDescriptorInterfaceDeleted" ), }, async (event) => { diff --git a/packages/m2m-event-dispatcher/src/services/event-builders/eserviceM2MEventBuilder.ts b/packages/m2m-event-dispatcher/src/services/event-builders/eserviceM2MEventBuilder.ts index c15baf16a5..6a6fbb4f1d 100644 --- a/packages/m2m-event-dispatcher/src/services/event-builders/eserviceM2MEventBuilder.ts +++ b/packages/m2m-event-dispatcher/src/services/event-builders/eserviceM2MEventBuilder.ts @@ -121,7 +121,8 @@ function getEServiceM2MEventVisibility( "EServiceDescriptorQuotasUpdated", "EServiceDescriptorAgreementApprovalPolicyUpdated", "EServiceDescriptorAttributesUpdated", - "EServicePersonalDataFlagUpdatedAfterPublication" + "EServicePersonalDataFlagUpdatedAfterPublication", + "EServicePersonalDataFlagUpdatedByTemplateUpdate" ), () => m2mEventVisibility.public ) diff --git a/packages/m2m-event-dispatcher/test/handleEServiceEvent.test.ts b/packages/m2m-event-dispatcher/test/handleEServiceEvent.test.ts index 4f2b2c3dc1..2c48a15a96 100644 --- a/packages/m2m-event-dispatcher/test/handleEServiceEvent.test.ts +++ b/packages/m2m-event-dispatcher/test/handleEServiceEvent.test.ts @@ -136,7 +136,8 @@ describe("handleEServiceEvent test", async () => { "EServiceIsClientAccessDelegableDisabled", "EServiceSignalHubEnabled", "EServiceSignalHubDisabled", - "EServicePersonalDataFlagUpdatedAfterPublication" + "EServicePersonalDataFlagUpdatedAfterPublication", + "EServicePersonalDataFlagUpdatedByTemplateUpdate" ), async () => [ { From 8010fee686ae1ebc729ad0071665cfd9158969d4 Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Mon, 6 Oct 2025 17:52:38 +0200 Subject: [PATCH 157/180] feat: add check for personalData flag when creating eService instances from template --- .../src/model/domain/errors.ts | 14 +++++++++ .../src/services/catalogService.ts | 31 +++++++++++++------ .../src/utilities/errorMappers.ts | 1 + ...createEServiceInstanceFromTemplate.test.ts | 24 +++++++++----- ...createEServiceInstanceFromTemplate.test.ts | 29 +++++++++++++++++ 5 files changed, 81 insertions(+), 18 deletions(-) diff --git a/packages/catalog-process/src/model/domain/errors.ts b/packages/catalog-process/src/model/domain/errors.ts index 2118bfa020..cf25fbd2dd 100644 --- a/packages/catalog-process/src/model/domain/errors.ts +++ b/packages/catalog-process/src/model/domain/errors.ts @@ -7,6 +7,7 @@ import { EServiceDocumentId, EServiceId, EServiceTemplateId, + EServiceTemplateVersionId, RiskAnalysisId, TenantId, TenantKind, @@ -57,6 +58,7 @@ export const errorCodes = { attributeDuplicatedInGroup: "0041", eservicePersonalDataFlagCanOnlyBeSetOnce: "0042", missingPersonalDataFlag: "0043", + eServiceTemplateWithoutPersonalDataFlag: "0044", }; export type ErrorCodes = keyof typeof errorCodes; @@ -498,3 +500,15 @@ export function missingPersonalDataFlag( title: "EService personalData flag must be set before publication", }); } + +export function eServiceTemplateWithoutPersonalDataFlag( + eServiceTemplateId: EServiceTemplateId, + eServiceTemplateVersionId: EServiceTemplateVersionId +): ApiError { + return new ApiError({ + detail: `Template version ${eServiceTemplateVersionId} in eService Template ${eServiceTemplateId} cannot be instantiated because the personalData flag is not set`, + code: "eServiceTemplateWithoutPersonalDataFlag", + title: + "EService Template personalData flag must be set before instantiation", + }); +} diff --git a/packages/catalog-process/src/services/catalogService.ts b/packages/catalog-process/src/services/catalogService.ts index e70eded1b6..6e1e1d668b 100644 --- a/packages/catalog-process/src/services/catalogService.ts +++ b/packages/catalog-process/src/services/catalogService.ts @@ -102,6 +102,7 @@ import { attributeDuplicatedInGroup, eservicePersonalDataFlagCanOnlyBeSetOnce, missingPersonalDataFlag, + eServiceTemplateWithoutPersonalDataFlag, } from "../model/domain/errors.js"; import { ApiGetEServicesFilters, Consumer } from "../model/domain/models.js"; import { @@ -181,7 +182,7 @@ import { ReadModelServiceSQL } from "./readModelServiceSQL.js"; const retrieveEService = async ( eserviceId: EServiceId, - readModelService: ReadModelServiceSQL + readModelService: ReadModelService ): Promise> => { const eservice = await readModelService.getEServiceById(eserviceId); if (eservice === undefined) { @@ -225,7 +226,7 @@ const retrieveDocument = ( const retrieveTenant = async ( tenantId: TenantId, - readModelService: Pick + readModelService: Pick ): Promise => { const tenant = await readModelService.getTenantById(tenantId); if (tenant === undefined) { @@ -268,7 +269,7 @@ const assertRequesterCanPublish = ( const retrieveActiveProducerDelegation = async ( eservice: EService, - readModelService: ReadModelServiceSQL + readModelService: ReadModelService ): Promise => await readModelService.getLatestDelegation({ eserviceId: eservice.id, @@ -278,7 +279,7 @@ const retrieveActiveProducerDelegation = async ( const retrieveEServiceTemplate = async ( eserviceTemplateId: EServiceTemplateId, - readModelService: ReadModelServiceSQL + readModelService: ReadModelService ): Promise => { const eserviceTemplate = await readModelService.getEServiceTemplateById( eserviceTemplateId @@ -416,7 +417,7 @@ const replaceRiskAnalysis = ( async function parseAndCheckAttributesOfKind( attributesSeedForKind: catalogApi.AttributeSeed[][], kind: AttributeKind, - readModelService: ReadModelServiceSQL + readModelService: ReadModelService ): Promise { const parsedAttributesSeed = attributesSeedForKind.map((group) => { const groupAttributesIdsFound: Set = new Set(); @@ -455,7 +456,7 @@ async function parseAndCheckAttributesOfKind( export async function parseAndCheckAttributes( attributesSeed: catalogApi.AttributesSeed, - readModelService: ReadModelServiceSQL + readModelService: ReadModelService ): Promise { const [certifiedAttributes, declaredAttributes, verifiedAttributes] = await Promise.all([ @@ -756,7 +757,7 @@ function createNextDescriptor( // eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function catalogServiceBuilder( dbInstance: DB, - readModelService: ReadModelServiceSQL, + readModelService: ReadModelService, fileManager: FileManager ) { const repository = eventRepository(dbInstance, catalogEventToBinaryData); @@ -3309,6 +3310,16 @@ export function catalogServiceBuilder( readModelService ); + if ( + config.featureFlagEservicePersonalData && + template.personalData === undefined + ) { + throw eServiceTemplateWithoutPersonalDataFlag( + template.id, + publishedVersion.id + ); + } + const { eService: createdEService, events } = await innerCreateEService( { seed: { @@ -3705,7 +3716,7 @@ async function createOpenApiInterfaceByTemplate( async function applyVisibilityToEService( eservice: EService, authData: UIAuthData | M2MAuthData | M2MAdminAuthData | InternalAuthData, - readModelService: ReadModelServiceSQL + readModelService: ReadModelService ): Promise { if (authData.systemRole === authRole.INTERNAL_ROLE) { return eservice; @@ -3768,7 +3779,7 @@ const deleteDescriptorInterfaceAndDocs = async ( const processDescriptorPublication = async ( eservice: EService, descriptor: Descriptor, - readModelService: ReadModelServiceSQL, + readModelService: ReadModelService, logger: Logger ): Promise => { const currentActiveDescriptor = eservice.descriptors.find( @@ -3905,7 +3916,7 @@ function evaluateTemplateVersionRef( async function extractEServiceRiskAnalysisFromTemplate( template: EServiceTemplate & { mode: typeof eserviceMode.receive }, requester: TenantId, - readModelService: ReadModelServiceSQL + readModelService: ReadModelService ): Promise { const tenant = await retrieveTenant(requester, readModelService); diff --git a/packages/catalog-process/src/utilities/errorMappers.ts b/packages/catalog-process/src/utilities/errorMappers.ts index cab84f25b0..716177a2c9 100644 --- a/packages/catalog-process/src/utilities/errorMappers.ts +++ b/packages/catalog-process/src/utilities/errorMappers.ts @@ -41,6 +41,7 @@ export const createEServiceInstanceFromTemplateErrorMapper = ( "inconsistentDailyCalls", "eServiceTemplateWithoutPublishedVersion", "templateMissingRequiredRiskAnalysis", + "eServiceTemplateWithoutPersonalDataFlag", () => HTTP_STATUS_BAD_REQUEST ) .with( diff --git a/packages/catalog-process/test/api/createEServiceInstanceFromTemplate.test.ts b/packages/catalog-process/test/api/createEServiceInstanceFromTemplate.test.ts index 2cfc51835e..fc676e4375 100644 --- a/packages/catalog-process/test/api/createEServiceInstanceFromTemplate.test.ts +++ b/packages/catalog-process/test/api/createEServiceInstanceFromTemplate.test.ts @@ -26,6 +26,7 @@ import { documentPrettyNameDuplicate, eServiceNameDuplicateForProducer, eServiceTemplateNotFound, + eServiceTemplateWithoutPersonalDataFlag, eServiceTemplateWithoutPublishedVersion, inconsistentDailyCalls, interfaceAlreadyExists, @@ -57,7 +58,7 @@ describe("API /templates/{templateId}/eservices authorization test", () => { }; const mockApiEservice: catalogApi.EService = catalogApi.EService.parse( - eServiceToApiEService(eService) + eServiceToApiEService(eService), ); catalogService.createEServiceInstanceFromTemplate = vi @@ -80,11 +81,11 @@ describe("API /templates/{templateId}/eservices authorization test", () => { expect(res.status).toBe(200); expect(res.body).toEqual(mockApiEservice); - } + }, ); it.each( - Object.values(authRole).filter((role) => !authorizedRoles.includes(role)) + Object.values(authRole).filter((role) => !authorizedRoles.includes(role)), )("Should return 403 for user with role %s", async (role) => { const token = generateToken(role); const res = await makeRequest(token, eServiceTemplate.id); @@ -104,7 +105,7 @@ describe("API /templates/{templateId}/eservices authorization test", () => { { error: eServiceNameDuplicateForProducer( eService.name, - eService.producerId + eService.producerId, ), expectedStatus: 409, }, @@ -140,7 +141,14 @@ describe("API /templates/{templateId}/eservices authorization test", () => { error: templateMissingRequiredRiskAnalysis( eServiceTemplate.id, generateId(), - tenantKind.PA + tenantKind.PA, + ), + expectedStatus: 400, + }, + { + error: eServiceTemplateWithoutPersonalDataFlag( + eServiceTemplate.id, + publishedVersion.id, ), expectedStatus: 400, }, @@ -155,7 +163,7 @@ describe("API /templates/{templateId}/eservices authorization test", () => { const res = await makeRequest(token, eServiceTemplate.id); expect(res.status).toBe(expectedStatus); - } + }, ); it.each([{}, { eServiceTemplateId: "invalidId" }])( @@ -164,10 +172,10 @@ describe("API /templates/{templateId}/eservices authorization test", () => { const token = generateToken(authRole.ADMIN_ROLE); const res = await makeRequest( token, - eServiceTemplateId as EServiceTemplateId + eServiceTemplateId as EServiceTemplateId, ); expect(res.status).toBe(400); - } + }, ); }); diff --git a/packages/catalog-process/test/integration/createEServiceInstanceFromTemplate.test.ts b/packages/catalog-process/test/integration/createEServiceInstanceFromTemplate.test.ts index 9d1c9d4d46..18175a4941 100644 --- a/packages/catalog-process/test/integration/createEServiceInstanceFromTemplate.test.ts +++ b/packages/catalog-process/test/integration/createEServiceInstanceFromTemplate.test.ts @@ -635,4 +635,33 @@ describe("create eService from template", () => { code: "eServiceTemplateWithoutPublishedVersion", }); }); + + it("should throw eServiceTemplateWithoutPersonalDataFlag when the template has no personalData flag and the feature flag is enabled", async () => { + const publishedVersion: EServiceTemplateVersion = { + ...getMockEServiceTemplateVersion(), + state: eserviceTemplateVersionState.published, + }; + const eServiceTemplate: EServiceTemplate = { + ...mockEServiceTemplate, + versions: [publishedVersion], + }; + + const tenant: Tenant = { + ...getMockTenant(mockEService.producerId), + kind: tenantKind.PA, + }; + + await addOneTenant(tenant); + await addOneEServiceTemplate(eServiceTemplate); + + await expect( + catalogService.createEServiceInstanceFromTemplate( + eServiceTemplate.id, + {}, + getMockContext({ authData: getMockAuthData(tenant.id) }) + ) + ).rejects.toMatchObject({ + code: "eServiceTemplateWithoutPersonalDataFlag", + }); + }); }); From ec8399bdbdc4b93f98be5b4cead8a48dd1852ad9 Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Mon, 6 Oct 2025 18:04:24 +0200 Subject: [PATCH 158/180] refactor: rename ReadModelService to ReadModelServiceSQL --- .../src/services/catalogService.ts | 12 ++++++------ .../createEServiceInstanceFromTemplate.test.ts | 18 +++++++++--------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/catalog-process/src/services/catalogService.ts b/packages/catalog-process/src/services/catalogService.ts index 6e1e1d668b..5c891e2b18 100644 --- a/packages/catalog-process/src/services/catalogService.ts +++ b/packages/catalog-process/src/services/catalogService.ts @@ -417,7 +417,7 @@ const replaceRiskAnalysis = ( async function parseAndCheckAttributesOfKind( attributesSeedForKind: catalogApi.AttributeSeed[][], kind: AttributeKind, - readModelService: ReadModelService + readModelService: ReadModelServiceSQL ): Promise { const parsedAttributesSeed = attributesSeedForKind.map((group) => { const groupAttributesIdsFound: Set = new Set(); @@ -456,7 +456,7 @@ async function parseAndCheckAttributesOfKind( export async function parseAndCheckAttributes( attributesSeed: catalogApi.AttributesSeed, - readModelService: ReadModelService + readModelService: ReadModelServiceSQL ): Promise { const [certifiedAttributes, declaredAttributes, verifiedAttributes] = await Promise.all([ @@ -757,7 +757,7 @@ function createNextDescriptor( // eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function catalogServiceBuilder( dbInstance: DB, - readModelService: ReadModelService, + readModelService: ReadModelServiceSQL, fileManager: FileManager ) { const repository = eventRepository(dbInstance, catalogEventToBinaryData); @@ -3716,7 +3716,7 @@ async function createOpenApiInterfaceByTemplate( async function applyVisibilityToEService( eservice: EService, authData: UIAuthData | M2MAuthData | M2MAdminAuthData | InternalAuthData, - readModelService: ReadModelService + readModelService: ReadModelServiceSQL ): Promise { if (authData.systemRole === authRole.INTERNAL_ROLE) { return eservice; @@ -3779,7 +3779,7 @@ const deleteDescriptorInterfaceAndDocs = async ( const processDescriptorPublication = async ( eservice: EService, descriptor: Descriptor, - readModelService: ReadModelService, + readModelService: ReadModelServiceSQL, logger: Logger ): Promise => { const currentActiveDescriptor = eservice.descriptors.find( @@ -3916,7 +3916,7 @@ function evaluateTemplateVersionRef( async function extractEServiceRiskAnalysisFromTemplate( template: EServiceTemplate & { mode: typeof eserviceMode.receive }, requester: TenantId, - readModelService: ReadModelService + readModelService: ReadModelServiceSQL ): Promise { const tenant = await retrieveTenant(requester, readModelService); diff --git a/packages/catalog-process/test/api/createEServiceInstanceFromTemplate.test.ts b/packages/catalog-process/test/api/createEServiceInstanceFromTemplate.test.ts index fc676e4375..d10f55c4d7 100644 --- a/packages/catalog-process/test/api/createEServiceInstanceFromTemplate.test.ts +++ b/packages/catalog-process/test/api/createEServiceInstanceFromTemplate.test.ts @@ -58,7 +58,7 @@ describe("API /templates/{templateId}/eservices authorization test", () => { }; const mockApiEservice: catalogApi.EService = catalogApi.EService.parse( - eServiceToApiEService(eService), + eServiceToApiEService(eService) ); catalogService.createEServiceInstanceFromTemplate = vi @@ -81,11 +81,11 @@ describe("API /templates/{templateId}/eservices authorization test", () => { expect(res.status).toBe(200); expect(res.body).toEqual(mockApiEservice); - }, + } ); it.each( - Object.values(authRole).filter((role) => !authorizedRoles.includes(role)), + Object.values(authRole).filter((role) => !authorizedRoles.includes(role)) )("Should return 403 for user with role %s", async (role) => { const token = generateToken(role); const res = await makeRequest(token, eServiceTemplate.id); @@ -105,7 +105,7 @@ describe("API /templates/{templateId}/eservices authorization test", () => { { error: eServiceNameDuplicateForProducer( eService.name, - eService.producerId, + eService.producerId ), expectedStatus: 409, }, @@ -141,14 +141,14 @@ describe("API /templates/{templateId}/eservices authorization test", () => { error: templateMissingRequiredRiskAnalysis( eServiceTemplate.id, generateId(), - tenantKind.PA, + tenantKind.PA ), expectedStatus: 400, }, { error: eServiceTemplateWithoutPersonalDataFlag( eServiceTemplate.id, - publishedVersion.id, + publishedVersion.id ), expectedStatus: 400, }, @@ -163,7 +163,7 @@ describe("API /templates/{templateId}/eservices authorization test", () => { const res = await makeRequest(token, eServiceTemplate.id); expect(res.status).toBe(expectedStatus); - }, + } ); it.each([{}, { eServiceTemplateId: "invalidId" }])( @@ -172,10 +172,10 @@ describe("API /templates/{templateId}/eservices authorization test", () => { const token = generateToken(authRole.ADMIN_ROLE); const res = await makeRequest( token, - eServiceTemplateId as EServiceTemplateId, + eServiceTemplateId as EServiceTemplateId ); expect(res.status).toBe(400); - }, + } ); }); From a5028c487f3024d911257c23cecdf48e61faefad Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Mon, 6 Oct 2025 18:07:14 +0200 Subject: [PATCH 159/180] refactor: rename ReadModelService to ReadModelServiceSQL --- packages/catalog-process/src/services/catalogService.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/catalog-process/src/services/catalogService.ts b/packages/catalog-process/src/services/catalogService.ts index 5c891e2b18..ce3cfa0b21 100644 --- a/packages/catalog-process/src/services/catalogService.ts +++ b/packages/catalog-process/src/services/catalogService.ts @@ -182,7 +182,7 @@ import { ReadModelServiceSQL } from "./readModelServiceSQL.js"; const retrieveEService = async ( eserviceId: EServiceId, - readModelService: ReadModelService + readModelService: ReadModelServiceSQL ): Promise> => { const eservice = await readModelService.getEServiceById(eserviceId); if (eservice === undefined) { @@ -226,7 +226,7 @@ const retrieveDocument = ( const retrieveTenant = async ( tenantId: TenantId, - readModelService: Pick + readModelService: Pick ): Promise => { const tenant = await readModelService.getTenantById(tenantId); if (tenant === undefined) { @@ -269,7 +269,7 @@ const assertRequesterCanPublish = ( const retrieveActiveProducerDelegation = async ( eservice: EService, - readModelService: ReadModelService + readModelService: ReadModelServiceSQL ): Promise => await readModelService.getLatestDelegation({ eserviceId: eservice.id, @@ -279,7 +279,7 @@ const retrieveActiveProducerDelegation = async ( const retrieveEServiceTemplate = async ( eserviceTemplateId: EServiceTemplateId, - readModelService: ReadModelService + readModelService: ReadModelServiceSQL ): Promise => { const eserviceTemplate = await readModelService.getEServiceTemplateById( eserviceTemplateId From 122d5a3e1161ec27f31cb6a71c3d527bd52f6123 Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Tue, 7 Oct 2025 10:08:10 +0200 Subject: [PATCH 160/180] feat(test): add personalData field to createEServiceInstanceFromTemplate tests --- .../integration/createEServiceInstanceFromTemplate.test.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/catalog-process/test/integration/createEServiceInstanceFromTemplate.test.ts b/packages/catalog-process/test/integration/createEServiceInstanceFromTemplate.test.ts index 18175a4941..ff597d6b0f 100644 --- a/packages/catalog-process/test/integration/createEServiceInstanceFromTemplate.test.ts +++ b/packages/catalog-process/test/integration/createEServiceInstanceFromTemplate.test.ts @@ -63,6 +63,7 @@ describe("create eService from template", () => { const eServiceTemplate: EServiceTemplate = { ...mockEServiceTemplate, versions: [publishedVersion], + personalData: false, }; const tenant: Tenant = { @@ -184,6 +185,7 @@ describe("create eService from template", () => { validEServiceTemplateRiskAnalysisPrivate, ], versions: [publishedVersion], + personalData: false, }; await addOneTenant(tenant); @@ -258,6 +260,7 @@ describe("create eService from template", () => { validEServiceTemplateRiskAnalysisPrivate, ], versions: [publishedVersion], + personalData: false, }; await addOneTenant(tenant); @@ -337,6 +340,7 @@ describe("create eService from template", () => { const eServiceTemplate: EServiceTemplate = { ...mockEServiceTemplate, versions: [eserviceTemplatePublishedVersion], + personalData: false, }; const tenant: Tenant = { From 8ea77a08656dca18a2942ffc8c02cff503725169 Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Wed, 8 Oct 2025 16:10:28 +0200 Subject: [PATCH 161/180] chore: refactor featureFlagEservicePersonalData --- .../src/services/eserviceTemplateService.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/eservice-template-process/src/services/eserviceTemplateService.ts b/packages/eservice-template-process/src/services/eserviceTemplateService.ts index f37bab6416..c2baeb5318 100644 --- a/packages/eservice-template-process/src/services/eserviceTemplateService.ts +++ b/packages/eservice-template-process/src/services/eserviceTemplateService.ts @@ -515,9 +515,8 @@ export function eserviceTemplateServiceBuilder( if (eserviceTemplate.data.mode === eserviceMode.receive) { assertRiskAnalysisIsValidForPublication(eserviceTemplate.data); } - if ( - config.featureFlagEservicePersonalData && + isFeatureFlagEnabled(config, "featureFlagEservicePersonalData") && eserviceTemplate.data.personalData === undefined ) { throw missingPersonalDataFlag( From da83e48cc9307cbc23a6be577ff2b081a2e284ac Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Wed, 8 Oct 2025 16:35:16 +0200 Subject: [PATCH 162/180] chore: refactor check featureFlagEservicePersonalData --- packages/catalog-process/src/services/catalogService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/catalog-process/src/services/catalogService.ts b/packages/catalog-process/src/services/catalogService.ts index fd647089b8..51b095a108 100644 --- a/packages/catalog-process/src/services/catalogService.ts +++ b/packages/catalog-process/src/services/catalogService.ts @@ -3330,7 +3330,7 @@ export function catalogServiceBuilder( ); if ( - config.featureFlagEservicePersonalData && + isFeatureFlagEnabled(config, "featureFlagEservicePersonalData") && template.personalData === undefined ) { throw eServiceTemplateWithoutPersonalDataFlag( From dc880020ba8b30111556d37815cf160feb4e42e6 Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Wed, 8 Oct 2025 16:41:51 +0200 Subject: [PATCH 163/180] chore: refactor check featureFlagEservicePersonalData --- .../src/services/eserviceTemplateService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eservice-template-process/src/services/eserviceTemplateService.ts b/packages/eservice-template-process/src/services/eserviceTemplateService.ts index c2baeb5318..bdfe122f2b 100644 --- a/packages/eservice-template-process/src/services/eserviceTemplateService.ts +++ b/packages/eservice-template-process/src/services/eserviceTemplateService.ts @@ -1313,7 +1313,7 @@ export function eserviceTemplateServiceBuilder( createdAt: creationDate, riskAnalysis: [], isSignalHubEnabled: seed.isSignalHubEnabled, - ...(config.featureFlagEservicePersonalData + ...(isFeatureFlagEnabled(config, "featureFlagEservicePersonalData") ? { personalData: seed.personalData } : {}), }; From b697168deee5b2225dc7ef230e100fd253916f20 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 9 Oct 2025 10:07:35 +0200 Subject: [PATCH 164/180] Fix error --- .../src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts b/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts index f7851bb72d..b626e77803 100644 --- a/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts +++ b/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts @@ -338,7 +338,7 @@ export async function handleMessageV2({ if (personalData === undefined) { throw missingKafkaMessageDataError( "eserviceTemplate.personalData", - "EServiceTemplatePersonalDataUpdatedAfterPublish" + "EServiceTemplatePersonalDataUpdatedAfterPublication" ); } const updateTemplateInstancePersonalData = async ( From 9f285972fe7ce8546058ab9a11fc80acd78cc3d1 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 9 Oct 2025 10:08:20 +0200 Subject: [PATCH 165/180] Fix error --- .../src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts b/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts index b626e77803..8ef6d2db70 100644 --- a/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts +++ b/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts @@ -338,7 +338,7 @@ export async function handleMessageV2({ if (personalData === undefined) { throw missingKafkaMessageDataError( "eserviceTemplate.personalData", - "EServiceTemplatePersonalDataUpdatedAfterPublication" + "EServiceTemplatePersonalDataFlagUpdatedAfterPublication" ); } const updateTemplateInstancePersonalData = async ( From 5eaebbf3b882202812e48d3601cc367a620a5e2f Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 9 Oct 2025 15:27:50 +0200 Subject: [PATCH 166/180] Improve type and add check on personalData --- .../risk-analysis/riskAnalysisValidation.ts | 54 ++++++++++++++++-- .../rules/riskAnalysisFormRulesProvider.ts | 57 +++++++++++++------ 2 files changed, 87 insertions(+), 24 deletions(-) diff --git a/packages/commons/src/risk-analysis/riskAnalysisValidation.ts b/packages/commons/src/risk-analysis/riskAnalysisValidation.ts index 9ae733820f..feddc1d5c5 100644 --- a/packages/commons/src/risk-analysis/riskAnalysisValidation.ts +++ b/packages/commons/src/risk-analysis/riskAnalysisValidation.ts @@ -1,4 +1,8 @@ -import { tenantKind, TenantKind } from "pagopa-interop-models"; +import { + genericInternalError, + tenantKind, + TenantKind, +} from "pagopa-interop-models"; import { P, match } from "ts-pattern"; import { RiskAnalysisFormToValidate, @@ -25,7 +29,11 @@ import { RiskAnalysisFormRules, dataType, } from "./rules/riskAnalysisFormRules.js"; -import { riskAnalysisFormRules } from "./rules/riskAnalysisFormRulesProvider.js"; +import { + buildLabel, + formRules, + riskAnalysisFormRules, +} from "./rules/riskAnalysisFormRulesProvider.js"; export function validateRiskAnalysis( riskAnalysisForm: RiskAnalysisFormToValidate, @@ -92,11 +100,14 @@ export function validateRiskAnalysis( multiAnswers: [], } ); + const personalDataInRiskAnalysys: boolean | undefined = true; // TODO retrieve actual value from answers - if (riskAnalysisForm.version === "3.1") { - console.log("TODO add actual check", personalDataInEService); - } - + validatePersonalDataFlag({ + tenantKind, + version: formRulesForValidation.version, + personalDataInRiskAnalysys, + personalDataInEService, + }); return validResult({ version: formRulesForValidation.version, singleAnswers, @@ -384,3 +395,34 @@ export function validResult(value: T): RiskAnalysisValidationResult { value, }; } + +const validatePersonalDataFlag = ({ + tenantKind, + version, + personalDataInRiskAnalysys, + personalDataInEService, +}: { + tenantKind: TenantKind; + version: string; + personalDataInRiskAnalysys: boolean | undefined; + personalDataInEService: boolean | undefined; +}): void => { + const label = buildLabel(tenantKind, version); + match(label) + .with(formRules.PA_1_0, () => void 0) + .with(formRules.PA_2_0, () => void 0) + .with(formRules.PA_3_0, () => void 0) + .with(formRules.PA_3_1, () => + match(personalDataInEService) + .with(P.boolean, () => { + if (personalDataInEService !== personalDataInRiskAnalysys) { + throw genericInternalError(""); + } + }) + .with(undefined, () => void 0) + .exhaustive() + ) + .with(formRules.PRIVATE_1_0, () => void 0) + .with(formRules.PRIVATE_2_0, () => void 0) + .exhaustive(); +}; diff --git a/packages/commons/src/risk-analysis/rules/riskAnalysisFormRulesProvider.ts b/packages/commons/src/risk-analysis/rules/riskAnalysisFormRulesProvider.ts index 063754cdf6..0b6c668b0d 100644 --- a/packages/commons/src/risk-analysis/rules/riskAnalysisFormRulesProvider.ts +++ b/packages/commons/src/risk-analysis/rules/riskAnalysisFormRulesProvider.ts @@ -1,5 +1,6 @@ -import { TenantKind } from "pagopa-interop-models"; +import { tenantKind, TenantKind } from "pagopa-interop-models"; import { match } from "ts-pattern"; +import { z } from "zod"; import { pa1 } from "./PA/1.0.js"; import { pa2 } from "./PA/2.0.js"; import { pa3 } from "./PA/3.0.js"; @@ -7,22 +8,41 @@ import { private1 } from "./PRIVATE/1.0.js"; import { private2 } from "./PRIVATE/2.0.js"; import { RiskAnalysisFormRules } from "./riskAnalysisFormRules.js"; -const formRules = { - pa1, - pa2, - pa3, - private1, - private2, -}; +export const formRules = { + PA_1_0: "PA-1.0", + PA_2_0: "PA-2.0", + PA_3_0: "PA-3.0", + PA_3_1: "PA-3.1", + PRIVATE_1_0: "PRIVATE-1.0", + PRIVATE_2_0: "PRIVATE-2.0", +} as const; +export const FormRules = z.enum([ + Object.values(formRules)[0], + ...Object.values(formRules).slice(1), +]); +export type FormRules = z.infer; + +export function buildLabel(kind: TenantKind, version: string): FormRules { + const kindForRA = kind === tenantKind.PA ? tenantKind.PA : tenantKind.PRIVATE; + const parsed = FormRules.safeParse(`${kindForRA}-${version}`); + + if (!parsed.success) { + throw new Error( + `Unsupported ruleset for kind ${kind} and version ${version}` + ); + } + return parsed.data; +} -function getFormRules(ruleset: keyof typeof formRules): RiskAnalysisFormRules { +function getFormRules(ruleset: FormRules): RiskAnalysisFormRules { return RiskAnalysisFormRules.parse( match(ruleset) - .with("pa1", () => pa1) - .with("pa2", () => pa2) - .with("pa3", () => pa3) - .with("private1", () => private1) - .with("private2", () => private2) + .with(formRules.PA_1_0, () => pa1) + .with(formRules.PA_2_0, () => pa2) + .with(formRules.PA_3_0, () => pa3) + .with(formRules.PA_3_1, () => pa3) // TODO replace with pa31 + .with(formRules.PRIVATE_1_0, () => private1) + .with(formRules.PRIVATE_2_0, () => private2) .exhaustive() ); } @@ -31,8 +51,9 @@ export const riskAnalysisFormRules: Record< TenantKind, RiskAnalysisFormRules[] > = { - PA: [getFormRules("pa1"), getFormRules("pa2"), getFormRules("pa3")], - PRIVATE: [getFormRules("private1"), getFormRules("private2")], - GSP: [getFormRules("private1"), getFormRules("private2")], - SCP: [getFormRules("private1"), getFormRules("private2")], + // TODO add PA 3.1 + PA: [getFormRules("PA-1.0"), getFormRules("PA-2.0"), getFormRules("PA-3.0")], + PRIVATE: [getFormRules("PRIVATE-1.0"), getFormRules("PRIVATE-2.0")], + GSP: [getFormRules("PRIVATE-1.0"), getFormRules("PRIVATE-2.0")], + SCP: [getFormRules("PRIVATE-1.0"), getFormRules("PRIVATE-2.0")], }; From 1537214327a1ce167c01323b016abb2917fde499 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 9 Oct 2025 15:29:40 +0200 Subject: [PATCH 167/180] Edit errors --- .../commons/src/risk-analysis/riskAnalysisValidation.ts | 2 +- .../risk-analysis/rules/riskAnalysisFormRulesProvider.ts | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/commons/src/risk-analysis/riskAnalysisValidation.ts b/packages/commons/src/risk-analysis/riskAnalysisValidation.ts index feddc1d5c5..6bb0fb6867 100644 --- a/packages/commons/src/risk-analysis/riskAnalysisValidation.ts +++ b/packages/commons/src/risk-analysis/riskAnalysisValidation.ts @@ -416,7 +416,7 @@ const validatePersonalDataFlag = ({ match(personalDataInEService) .with(P.boolean, () => { if (personalDataInEService !== personalDataInRiskAnalysys) { - throw genericInternalError(""); + throw genericInternalError("Incompatible personalData flag"); } }) .with(undefined, () => void 0) diff --git a/packages/commons/src/risk-analysis/rules/riskAnalysisFormRulesProvider.ts b/packages/commons/src/risk-analysis/rules/riskAnalysisFormRulesProvider.ts index 0b6c668b0d..62f2fec76e 100644 --- a/packages/commons/src/risk-analysis/rules/riskAnalysisFormRulesProvider.ts +++ b/packages/commons/src/risk-analysis/rules/riskAnalysisFormRulesProvider.ts @@ -1,4 +1,8 @@ -import { tenantKind, TenantKind } from "pagopa-interop-models"; +import { + genericInternalError, + tenantKind, + TenantKind, +} from "pagopa-interop-models"; import { match } from "ts-pattern"; import { z } from "zod"; import { pa1 } from "./PA/1.0.js"; @@ -27,7 +31,7 @@ export function buildLabel(kind: TenantKind, version: string): FormRules { const parsed = FormRules.safeParse(`${kindForRA}-${version}`); if (!parsed.success) { - throw new Error( + throw genericInternalError( `Unsupported ruleset for kind ${kind} and version ${version}` ); } From e74e5e1118e09de88c7df8ab3d28537a10665db2 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 9 Oct 2025 16:14:01 +0200 Subject: [PATCH 168/180] Fix typo --- .../src/risk-analysis/riskAnalysisValidation.ts | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/packages/commons/src/risk-analysis/riskAnalysisValidation.ts b/packages/commons/src/risk-analysis/riskAnalysisValidation.ts index 6bb0fb6867..765bab505d 100644 --- a/packages/commons/src/risk-analysis/riskAnalysisValidation.ts +++ b/packages/commons/src/risk-analysis/riskAnalysisValidation.ts @@ -100,12 +100,12 @@ export function validateRiskAnalysis( multiAnswers: [], } ); - const personalDataInRiskAnalysys: boolean | undefined = true; // TODO retrieve actual value from answers + const personalDataInRiskAnalysis: boolean | undefined = true; // TODO retrieve actual value from answers validatePersonalDataFlag({ tenantKind, version: formRulesForValidation.version, - personalDataInRiskAnalysys, + personalDataInRiskAnalysis, personalDataInEService, }); return validResult({ @@ -399,30 +399,27 @@ export function validResult(value: T): RiskAnalysisValidationResult { const validatePersonalDataFlag = ({ tenantKind, version, - personalDataInRiskAnalysys, + personalDataInRiskAnalysis, personalDataInEService, }: { tenantKind: TenantKind; version: string; - personalDataInRiskAnalysys: boolean | undefined; + personalDataInRiskAnalysis: boolean | undefined; personalDataInEService: boolean | undefined; }): void => { const label = buildLabel(tenantKind, version); match(label) - .with(formRules.PA_1_0, () => void 0) - .with(formRules.PA_2_0, () => void 0) - .with(formRules.PA_3_0, () => void 0) + .with(formRules.PA_1_0, formRules.PA_2_0, formRules.PA_3_0, () => void 0) .with(formRules.PA_3_1, () => match(personalDataInEService) .with(P.boolean, () => { - if (personalDataInEService !== personalDataInRiskAnalysys) { + if (personalDataInEService !== personalDataInRiskAnalysis) { throw genericInternalError("Incompatible personalData flag"); } }) .with(undefined, () => void 0) .exhaustive() ) - .with(formRules.PRIVATE_1_0, () => void 0) - .with(formRules.PRIVATE_2_0, () => void 0) + .with(formRules.PRIVATE_1_0, formRules.PRIVATE_2_0, () => void 0) .exhaustive(); }; From 244e5a2167aefcc62a84abf65314ee0dcb9f2133 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 9 Oct 2025 16:38:33 +0200 Subject: [PATCH 169/180] Fix tests --- ...riskAnalysisValidation.integration.test.ts | 237 +++++++++++------- .../activatePurposeVersion.test.ts | 3 +- packages/purpose-process/test/mockUtils.ts | 3 +- 3 files changed, 145 insertions(+), 98 deletions(-) diff --git a/packages/commons-test/test/riskAnalysisValidation.integration.test.ts b/packages/commons-test/test/riskAnalysisValidation.integration.test.ts index ff2ae7a893..43fb9930e9 100644 --- a/packages/commons-test/test/riskAnalysisValidation.integration.test.ts +++ b/packages/commons-test/test/riskAnalysisValidation.integration.test.ts @@ -31,13 +31,15 @@ describe("Risk Analysis Validation", () => { validRiskAnalysis3_0_Pa, false, "PA", - new Date() + new Date(), + undefined ); const resultSchemaOnly = validateRiskAnalysis( validRiskAnalysis3_0_Pa, true, "PA", - new Date() + new Date(), + undefined ); expect(result).toEqual({ type: "valid", @@ -55,13 +57,15 @@ describe("Risk Analysis Validation", () => { expiredRiskAnalysis2_0_Pa, false, "PA", - new Date() + new Date(), + undefined ); const resultSchemaOnly = validateRiskAnalysis( expiredRiskAnalysis2_0_Pa, true, "PA", - new Date() + new Date(), + undefined ); expect(result).toEqual({ type: "valid", @@ -82,7 +86,8 @@ describe("Risk Analysis Validation", () => { validSchemaOnlyRiskAnalysis3_0_Pa, true, "PA", - new Date() + new Date(), + undefined ); expect(result).toEqual({ @@ -96,13 +101,15 @@ describe("Risk Analysis Validation", () => { validRiskAnalysis2_0_Private, false, "PRIVATE", - new Date() + new Date(), + undefined ); const resultSchemaOnly = validateRiskAnalysis( validRiskAnalysis2_0_Private, true, "PRIVATE", - new Date() + new Date(), + undefined ); expect(result).toEqual({ @@ -123,7 +130,8 @@ describe("Risk Analysis Validation", () => { validSchemaOnlyRiskAnalysis2_0_Private, true, "PRIVATE", - new Date() + new Date(), + undefined ); expect(result).toEqual({ @@ -137,13 +145,15 @@ describe("Risk Analysis Validation", () => { validRiskAnalysis2_0_Private, false, "GSP", - new Date() + new Date(), + undefined ); const resultSchemaOnly = validateRiskAnalysis( validRiskAnalysis2_0_Private, true, "GSP", - new Date() + new Date(), + undefined ); expect(result).toEqual({ @@ -164,7 +174,8 @@ describe("Risk Analysis Validation", () => { validSchemaOnlyRiskAnalysis2_0_Private, true, "GSP", - new Date() + new Date(), + undefined ); expect(result).toEqual({ @@ -181,7 +192,13 @@ describe("Risk Analysis Validation", () => { }; expect( - validateRiskAnalysis(invalidRiskAnalysis, false, "PA", new Date()) + validateRiskAnalysis( + invalidRiskAnalysis, + false, + "PA", + new Date(), + undefined + ) ).toEqual({ type: "invalid", issues: [rulesVersionNotFoundError("PA", invalidVersionForPA)], @@ -194,7 +211,13 @@ describe("Risk Analysis Validation", () => { }; expect( - validateRiskAnalysis(invalidRiskAnalysis2, false, "PRIVATE", new Date()) + validateRiskAnalysis( + invalidRiskAnalysis2, + false, + "PRIVATE", + new Date(), + undefined + ) ).toEqual({ type: "invalid", issues: [rulesVersionNotFoundError("PRIVATE", invalidVersionForPrivate)], @@ -209,7 +232,13 @@ describe("Risk Analysis Validation", () => { }; expect( - validateRiskAnalysis(expiredRiskAnalysis, false, "PA", new Date()) + validateRiskAnalysis( + expiredRiskAnalysis, + false, + "PA", + new Date(), + undefined + ) ).toEqual({ type: "invalid", issues: [expiredRulesVersionError(expiredVersionForPA, tenantKind.PA)], @@ -222,7 +251,13 @@ describe("Risk Analysis Validation", () => { }; expect( - validateRiskAnalysis(expiredRiskAnalysis2, false, "PRIVATE", new Date()) + validateRiskAnalysis( + expiredRiskAnalysis2, + false, + "PRIVATE", + new Date(), + undefined + ) ).toEqual({ type: "invalid", issues: [expiredRulesVersionError(expiredVersionForPrivate, "PRIVATE")], @@ -241,17 +276,17 @@ describe("Risk Analysis Validation", () => { }, }; - expect(validateRiskAnalysis(riskAnalysis, false, "PA", new Date())).toEqual( - { - type: "invalid", - issues: [ - dependencyNotFoundError("reasonPolicyNotProvided", "policyProvided"), - dependencyNotFoundError("confirmedDoneDpia", "doneDpia"), - missingExpectedFieldError("policyProvided"), - missingExpectedFieldError("doneDpia"), - ], - } - ); + expect( + validateRiskAnalysis(riskAnalysis, false, "PA", new Date(), undefined) + ).toEqual({ + type: "invalid", + issues: [ + dependencyNotFoundError("reasonPolicyNotProvided", "policyProvided"), + dependencyNotFoundError("confirmedDoneDpia", "doneDpia"), + missingExpectedFieldError("policyProvided"), + missingExpectedFieldError("doneDpia"), + ], + }); }); it("should succeed schema only even if a provided answer depends on a missing field", () => { @@ -265,7 +300,9 @@ describe("Risk Analysis Validation", () => { }, }; - expect(validateRiskAnalysis(riskAnalysis, true, "PA", new Date())).toEqual({ + expect( + validateRiskAnalysis(riskAnalysis, true, "PA", new Date(), undefined) + ).toEqual({ type: "valid", value: { version: validRiskAnalysis3_0_Pa.version, @@ -290,29 +327,29 @@ describe("Risk Analysis Validation", () => { }, }; - expect(validateRiskAnalysis(riskAnalysis, false, "PA", new Date())).toEqual( - { - type: "invalid", - issues: [ - unexpectedDependencyValueError( - "legalBasisPublicInterest", - "legalBasis", - "PUBLIC_INTEREST" - ), - unexpectedDependencyValueError( - "ruleOfLawText", - "legalBasisPublicInterest", - "RULE_OF_LAW" - ), - unexpectedDependencyValueError( - "ruleOfLawText", - "legalBasis", - "PUBLIC_INTEREST" - ), - unexpectedDependencyValueError("otherPurpose", "purpose", "OTHER"), - ], - } - ); + expect( + validateRiskAnalysis(riskAnalysis, false, "PA", new Date(), undefined) + ).toEqual({ + type: "invalid", + issues: [ + unexpectedDependencyValueError( + "legalBasisPublicInterest", + "legalBasis", + "PUBLIC_INTEREST" + ), + unexpectedDependencyValueError( + "ruleOfLawText", + "legalBasisPublicInterest", + "RULE_OF_LAW" + ), + unexpectedDependencyValueError( + "ruleOfLawText", + "legalBasis", + "PUBLIC_INTEREST" + ), + unexpectedDependencyValueError("otherPurpose", "purpose", "OTHER"), + ], + }); }); it("should succeed schema only even if a provided answer depends on an existing field with an unexpected value", () => { @@ -326,7 +363,9 @@ describe("Risk Analysis Validation", () => { }, }; - expect(validateRiskAnalysis(riskAnalysis, true, "PA", new Date())).toEqual({ + expect( + validateRiskAnalysis(riskAnalysis, true, "PA", new Date(), undefined) + ).toEqual({ type: "valid", value: { version: riskAnalysis.version, @@ -355,15 +394,15 @@ describe("Risk Analysis Validation", () => { }, }; - expect(validateRiskAnalysis(riskAnalysis, false, "PA", new Date())).toEqual( - { - type: "invalid", - issues: [ - missingExpectedFieldError("deliveryMethod"), - missingExpectedFieldError("doneDpia"), - ], - } - ); + expect( + validateRiskAnalysis(riskAnalysis, false, "PA", new Date(), undefined) + ).toEqual({ + type: "invalid", + issues: [ + missingExpectedFieldError("deliveryMethod"), + missingExpectedFieldError("doneDpia"), + ], + }); }); it("should succeeed schema only even on missing expected answers", () => { @@ -378,7 +417,9 @@ describe("Risk Analysis Validation", () => { }, }; - expect(validateRiskAnalysis(riskAnalysis, true, "PA", new Date())).toEqual({ + expect( + validateRiskAnalysis(riskAnalysis, true, "PA", new Date(), undefined) + ).toEqual({ type: "valid", value: { version: riskAnalysis.version, @@ -404,20 +445,22 @@ describe("Risk Analysis Validation", () => { }, }; - expect(validateRiskAnalysis(riskAnalysis, false, "PA", new Date())).toEqual( - validateRiskAnalysis(riskAnalysis, true, "PA", new Date()) + expect( + validateRiskAnalysis(riskAnalysis, false, "PA", new Date(), undefined) + ).toEqual( + validateRiskAnalysis(riskAnalysis, true, "PA", new Date(), undefined) ); - expect(validateRiskAnalysis(riskAnalysis, false, "PA", new Date())).toEqual( - { - type: "invalid", - issues: [ - unexpectedFieldError("unexpectedFieldA"), - unexpectedFieldError("unexpectedFieldB"), - unexpectedFieldError("unexpectedFieldC"), - ], - } - ); + expect( + validateRiskAnalysis(riskAnalysis, false, "PA", new Date(), undefined) + ).toEqual({ + type: "invalid", + issues: [ + unexpectedFieldError("unexpectedFieldA"), + unexpectedFieldError("unexpectedFieldB"), + unexpectedFieldError("unexpectedFieldC"), + ], + }); }); it("should fail on unexpected field value both schema only and not", () => { @@ -431,30 +474,32 @@ describe("Risk Analysis Validation", () => { }, }; - expect(validateRiskAnalysis(riskAnalysis, false, "PA", new Date())).toEqual( - validateRiskAnalysis(riskAnalysis, true, "PA", new Date()) + expect( + validateRiskAnalysis(riskAnalysis, false, "PA", new Date(), undefined) + ).toEqual( + validateRiskAnalysis(riskAnalysis, true, "PA", new Date(), undefined) ); - expect(validateRiskAnalysis(riskAnalysis, false, "PA", new Date())).toEqual( - { - type: "invalid", - issues: [ - unexpectedFieldValueError( - "purpose", - new Set(["INSTITUTIONAL", "OTHER"]) - ), - unexpectedFieldValueError( - "legalBasis", - new Set([ - "CONSENT", - "CONTRACT", - "LEGAL_OBLIGATION", - "SAFEGUARD", - "PUBLIC_INTEREST", - ]) - ), - ], - } - ); + expect( + validateRiskAnalysis(riskAnalysis, false, "PA", new Date(), undefined) + ).toEqual({ + type: "invalid", + issues: [ + unexpectedFieldValueError( + "purpose", + new Set(["INSTITUTIONAL", "OTHER"]) + ), + unexpectedFieldValueError( + "legalBasis", + new Set([ + "CONSENT", + "CONTRACT", + "LEGAL_OBLIGATION", + "SAFEGUARD", + "PUBLIC_INTEREST", + ]) + ), + ], + }); }); }); diff --git a/packages/purpose-process/test/integration/activatePurposeVersion.test.ts b/packages/purpose-process/test/integration/activatePurposeVersion.test.ts index 95fd78a8a9..8bb6851f9c 100644 --- a/packages/purpose-process/test/integration/activatePurposeVersion.test.ts +++ b/packages/purpose-process/test/integration/activatePurposeVersion.test.ts @@ -1507,7 +1507,8 @@ describe("activatePurposeVersion", () => { riskAnalysisFormToRiskAnalysisFormToValidate(riskAnalysisForm), false, mockConsumer.kind as TenantKind, - new Date() + new Date(), + undefined ); expect(async () => { diff --git a/packages/purpose-process/test/mockUtils.ts b/packages/purpose-process/test/mockUtils.ts index 455f975270..2d038d8b6c 100644 --- a/packages/purpose-process/test/mockUtils.ts +++ b/packages/purpose-process/test/mockUtils.ts @@ -92,7 +92,8 @@ export const createUpdatedPurpose = ( purposeUpdateContent.riskAnalysisForm, false, tenantKind, - new Date() + new Date(), + undefined )!, writtenRiskAnalysisForm ), From 24522108ef0f63eaafb938c5468bceb1b670e9eb Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 9 Oct 2025 17:15:14 +0200 Subject: [PATCH 170/180] update answer retrieval --- .../commons/src/risk-analysis/riskAnalysisValidation.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/commons/src/risk-analysis/riskAnalysisValidation.ts b/packages/commons/src/risk-analysis/riskAnalysisValidation.ts index 765bab505d..fc3ee9e84d 100644 --- a/packages/commons/src/risk-analysis/riskAnalysisValidation.ts +++ b/packages/commons/src/risk-analysis/riskAnalysisValidation.ts @@ -100,7 +100,12 @@ export function validateRiskAnalysis( multiAnswers: [], } ); - const personalDataInRiskAnalysis: boolean | undefined = true; // TODO retrieve actual value from answers + const personalDataInRiskAnalysis = match( + singleAnswers.find((a) => a.key === "usesPersonalData")?.value + ) + .with("YES", () => true) + .with("NO", () => false) + .otherwise(() => undefined); validatePersonalDataFlag({ tenantKind, From 0be3944d5b0d33fb602357ace4beb427c4cac90b Mon Sep 17 00:00:00 2001 From: Eduardo Mihalache Date: Thu, 9 Oct 2025 17:34:46 +0200 Subject: [PATCH 171/180] chore(m2m-gateway): add personalData to eserviceTemplates field test mocks --- .../eServiceTemplates/createEServiceTemplate.test.ts | 1 + .../integration/eServiceTemplates/getEServiceTemplates.test.ts | 2 ++ .../eServiceTemplates/updateDraftEserviceTemplate.test.ts | 1 + .../updatePublishedEServiceTemplateDescription.test.ts | 1 + .../updatePublishedEServiceTemplateIntendedTarget.test.ts | 1 + .../updatePublishedEServiceTemplateName.test.ts | 1 + 6 files changed, 7 insertions(+) diff --git a/packages/m2m-gateway/test/integration/eServiceTemplates/createEServiceTemplate.test.ts b/packages/m2m-gateway/test/integration/eServiceTemplates/createEServiceTemplate.test.ts index adc54213fd..2c52e5837e 100644 --- a/packages/m2m-gateway/test/integration/eServiceTemplates/createEServiceTemplate.test.ts +++ b/packages/m2m-gateway/test/integration/eServiceTemplates/createEServiceTemplate.test.ts @@ -80,6 +80,7 @@ describe("createEServiceTemplate", () => { creatorId: mockEserviceTemplateProcessResponse.data.creatorId, isSignalHubEnabled: mockEserviceTemplateProcessResponse.data.isSignalHubEnabled, + personalData: mockEserviceTemplateProcessResponse.data.personalData, }; const result = await eserviceTemplateService.createEServiceTemplate( diff --git a/packages/m2m-gateway/test/integration/eServiceTemplates/getEServiceTemplates.test.ts b/packages/m2m-gateway/test/integration/eServiceTemplates/getEServiceTemplates.test.ts index 9c36730852..829e61c20a 100644 --- a/packages/m2m-gateway/test/integration/eServiceTemplates/getEServiceTemplates.test.ts +++ b/packages/m2m-gateway/test/integration/eServiceTemplates/getEServiceTemplates.test.ts @@ -61,6 +61,7 @@ describe("getEserviceTemplates", () => { intendedTarget: mockApiEserviceTemplate1.intendedTarget, creatorId: mockApiEserviceTemplate1.creatorId, isSignalHubEnabled: mockApiEserviceTemplate1.isSignalHubEnabled, + personalData: mockApiEserviceTemplate1.personalData, }; const eserviceResponse2: m2mGatewayApi.EServiceTemplate = { @@ -72,6 +73,7 @@ describe("getEserviceTemplates", () => { intendedTarget: mockApiEserviceTemplate2.intendedTarget, creatorId: mockApiEserviceTemplate2.creatorId, isSignalHubEnabled: mockApiEserviceTemplate2.isSignalHubEnabled, + personalData: mockApiEserviceTemplate2.personalData, }; const eserviceTemplatesResponse: m2mGatewayApi.EServiceTemplates = { diff --git a/packages/m2m-gateway/test/integration/eServiceTemplates/updateDraftEserviceTemplate.test.ts b/packages/m2m-gateway/test/integration/eServiceTemplates/updateDraftEserviceTemplate.test.ts index 1013728cfc..81539bbf3c 100644 --- a/packages/m2m-gateway/test/integration/eServiceTemplates/updateDraftEserviceTemplate.test.ts +++ b/packages/m2m-gateway/test/integration/eServiceTemplates/updateDraftEserviceTemplate.test.ts @@ -71,6 +71,7 @@ describe("updateDraftEServiceTemplate", () => { intendedTarget: mockEServiceTemplateProcessGetResponse.data.intendedTarget, creatorId: mockEServiceTemplateProcessGetResponse.data.creatorId, + personalData: mockEServiceTemplateProcessGetResponse.data.personalData, }; expect(result).toEqual(expectedM2MEServiceTemplate); diff --git a/packages/m2m-gateway/test/integration/eServiceTemplates/updatePublishedEServiceTemplateDescription.test.ts b/packages/m2m-gateway/test/integration/eServiceTemplates/updatePublishedEServiceTemplateDescription.test.ts index 419c8bbcfa..8b7316b2a7 100644 --- a/packages/m2m-gateway/test/integration/eServiceTemplates/updatePublishedEServiceTemplateDescription.test.ts +++ b/packages/m2m-gateway/test/integration/eServiceTemplates/updatePublishedEServiceTemplateDescription.test.ts @@ -66,6 +66,7 @@ describe("updatePublishedEServiceTemplateDescription", () => { intendedTarget: mockEServiceTemplateProcessGetResponse.data.intendedTarget, creatorId: mockEServiceTemplateProcessGetResponse.data.creatorId, + personalData: mockEServiceTemplateProcessGetResponse.data.personalData, }; expect(result).toEqual(expectedM2MEServiceTemplate); diff --git a/packages/m2m-gateway/test/integration/eServiceTemplates/updatePublishedEServiceTemplateIntendedTarget.test.ts b/packages/m2m-gateway/test/integration/eServiceTemplates/updatePublishedEServiceTemplateIntendedTarget.test.ts index 3e094ec048..17a7d021b6 100644 --- a/packages/m2m-gateway/test/integration/eServiceTemplates/updatePublishedEServiceTemplateIntendedTarget.test.ts +++ b/packages/m2m-gateway/test/integration/eServiceTemplates/updatePublishedEServiceTemplateIntendedTarget.test.ts @@ -67,6 +67,7 @@ describe("updatePublishedEServiceTemplateIntendedTarget", () => { intendedTarget: mockEServiceTemplateProcessGetResponse.data.intendedTarget, creatorId: mockEServiceTemplateProcessGetResponse.data.creatorId, + personalData: mockEServiceTemplateProcessGetResponse.data.personalData, }; expect(result).toEqual(expectedM2MEServiceTemplate); diff --git a/packages/m2m-gateway/test/integration/eServiceTemplates/updatePublishedEServiceTemplateName.test.ts b/packages/m2m-gateway/test/integration/eServiceTemplates/updatePublishedEServiceTemplateName.test.ts index 0a054d0220..9e61c93f9b 100644 --- a/packages/m2m-gateway/test/integration/eServiceTemplates/updatePublishedEServiceTemplateName.test.ts +++ b/packages/m2m-gateway/test/integration/eServiceTemplates/updatePublishedEServiceTemplateName.test.ts @@ -66,6 +66,7 @@ describe("updatePublishedEServiceTemplateName", () => { intendedTarget: mockEServiceTemplateProcessGetResponse.data.intendedTarget, creatorId: mockEServiceTemplateProcessGetResponse.data.creatorId, + personalData: mockEServiceTemplateProcessGetResponse.data.personalData, }; expect(result).toEqual(expectedM2MEServiceTemplate); From 875cb1ac32c800a7ace7c0a6b17bf4aef07fb5d6 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Fri, 10 Oct 2025 14:48:00 +0200 Subject: [PATCH 172/180] Remove error to allow reprocess --- .../src/services/catalogService.ts | 2 +- .../src/utilities/errorMappers.ts | 4 --- ...teTemplateInstancePersonalDataFlag.test.ts | 30 +------------------ 3 files changed, 2 insertions(+), 34 deletions(-) diff --git a/packages/catalog-process/src/services/catalogService.ts b/packages/catalog-process/src/services/catalogService.ts index 305ecc249b..898c7699ed 100644 --- a/packages/catalog-process/src/services/catalogService.ts +++ b/packages/catalog-process/src/services/catalogService.ts @@ -2958,7 +2958,7 @@ export function catalogServiceBuilder( const eservice = await retrieveEService(eserviceId, readModelService); if (eservice.data.personalData !== undefined) { - throw eservicePersonalDataFlagCanOnlyBeSetOnce(eserviceId); + return; } const updatedEservice: EService = { diff --git a/packages/catalog-process/src/utilities/errorMappers.ts b/packages/catalog-process/src/utilities/errorMappers.ts index cab84f25b0..4c3be3c6b8 100644 --- a/packages/catalog-process/src/utilities/errorMappers.ts +++ b/packages/catalog-process/src/utilities/errorMappers.ts @@ -561,10 +561,6 @@ export const updateTemplateInstancePersonalDataErrorMapper = ( ): number => match(error.code) .with("eServiceNotFound", () => HTTP_STATUS_NOT_FOUND) - .with( - "eservicePersonalDataFlagCanOnlyBeSetOnce", - () => HTTP_STATUS_CONFLICT - ) .otherwise(() => HTTP_STATUS_INTERNAL_SERVER_ERROR); export const updateTemplateInstanceDescriptorVoucherLifespanErrorMapper = ( diff --git a/packages/catalog-process/test/integration/updateTemplateInstancePersonalDataFlag.test.ts b/packages/catalog-process/test/integration/updateTemplateInstancePersonalDataFlag.test.ts index 1115999315..038a1f0f51 100644 --- a/packages/catalog-process/test/integration/updateTemplateInstancePersonalDataFlag.test.ts +++ b/packages/catalog-process/test/integration/updateTemplateInstancePersonalDataFlag.test.ts @@ -15,10 +15,7 @@ import { EServicePersonalDataFlagUpdatedByTemplateUpdateV2, } from "pagopa-interop-models"; import { expect, describe, it } from "vitest"; -import { - eServiceNotFound, - eservicePersonalDataFlagCanOnlyBeSetOnce, -} from "../../src/model/domain/errors.js"; +import { eServiceNotFound } from "../../src/model/domain/errors.js"; import { addOneEService, catalogService, @@ -76,29 +73,4 @@ describe("internalUpdateTemplateInstancePersonalDataFlag", () => { ) ).rejects.toThrowError(eServiceNotFound(eservice.id)); }); - - it("should throw eservicePersonalDataFlagCanOnlyBeSetOnce if the personalData flag was already set", async () => { - const descriptor: Descriptor = { - ...getMockDescriptor(descriptorState.published), - interface: getMockDocument(), - }; - - const eservice: EService = { - ...getMockEService(), - descriptors: [descriptor], - personalData: true, - }; - - await addOneEService(eservice); - - await expect( - catalogService.updateEServicePersonalDataFlagAfterPublication( - eservice.id, - false, - getMockContext({ authData: getMockAuthData(eservice.producerId) }) - ) - ).rejects.toThrowError( - eservicePersonalDataFlagCanOnlyBeSetOnce(eservice.id) - ); - }); }); From cb1dc0825424d68113350fa7e82c3334fdf6ab40 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Fri, 10 Oct 2025 14:52:49 +0200 Subject: [PATCH 173/180] Fix duplicate handler --- .../src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts b/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts index 44ab187ebf..8ef6d2db70 100644 --- a/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts +++ b/packages/eservice-template-instances-updater/src/eserviceTemplateInstancesUpdaterConsumerServiceV2.ts @@ -382,7 +382,6 @@ export async function handleMessageV2({ { type: "EServiceTemplateVersionInterfaceUpdated" }, { type: "EServiceTemplateVersionPublished" }, { type: "EServiceTemplateVersionSuspended" }, - { type: "EServiceTemplatePersonalDataFlagUpdatedAfterPublication" }, () => Promise.resolve ) .exhaustive(); From 4cd5dbe28eab7121429e58bcf6e087adccdbc6fb Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Fri, 10 Oct 2025 15:23:44 +0200 Subject: [PATCH 174/180] Fix test --- .../eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts b/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts index 693679dfad..aedad496f5 100644 --- a/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts +++ b/packages/eservice-template-instances-updater/test/eserviceTemplateInstancesUpdaterConsumerServiceV2.test.ts @@ -990,7 +990,6 @@ describe("eserviceTemplateUpdaterConsumerServiceV2", () => { "EServiceTemplateVersionInterfaceUpdated", "EServiceTemplateVersionPublished", "EServiceTemplateVersionSuspended", - "EServiceTemplatePersonalDataFlagUpdatedAfterPublication", ] as const)("Should ignore %s event", async (eventType) => { const decodedKafkaMessage: EServiceTemplateEventEnvelope = { sequence_num: 1, From 6231812c4fc6c4a67a9c446ab1c6b4e84845d8df Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 13 Oct 2025 15:58:01 +0200 Subject: [PATCH 175/180] Add check for private 2_0 --- .../src/risk-analysis/riskAnalysisValidation.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/commons/src/risk-analysis/riskAnalysisValidation.ts b/packages/commons/src/risk-analysis/riskAnalysisValidation.ts index fc3ee9e84d..aa40716c3d 100644 --- a/packages/commons/src/risk-analysis/riskAnalysisValidation.ts +++ b/packages/commons/src/risk-analysis/riskAnalysisValidation.ts @@ -414,8 +414,14 @@ const validatePersonalDataFlag = ({ }): void => { const label = buildLabel(tenantKind, version); match(label) - .with(formRules.PA_1_0, formRules.PA_2_0, formRules.PA_3_0, () => void 0) - .with(formRules.PA_3_1, () => + .with( + formRules.PA_1_0, + formRules.PA_2_0, + formRules.PA_3_0, + formRules.PRIVATE_1_0, + () => void 0 + ) + .with(formRules.PA_3_1, formRules.PRIVATE_2_0, () => match(personalDataInEService) .with(P.boolean, () => { if (personalDataInEService !== personalDataInRiskAnalysis) { @@ -425,6 +431,5 @@ const validatePersonalDataFlag = ({ .with(undefined, () => void 0) .exhaustive() ) - .with(formRules.PRIVATE_1_0, formRules.PRIVATE_2_0, () => void 0) .exhaustive(); }; From 1aaa3e431f4ac56b25d748b1d005dd948e43e914 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Tue, 14 Oct 2025 12:38:04 +0200 Subject: [PATCH 176/180] Refactor --- .../risk-analysis/riskAnalysisValidation.ts | 25 +++++++++++-------- .../riskAnalysisValidationErrors.ts | 10 +++++++- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/packages/commons/src/risk-analysis/riskAnalysisValidation.ts b/packages/commons/src/risk-analysis/riskAnalysisValidation.ts index aa40716c3d..822db9a22d 100644 --- a/packages/commons/src/risk-analysis/riskAnalysisValidation.ts +++ b/packages/commons/src/risk-analysis/riskAnalysisValidation.ts @@ -1,8 +1,4 @@ -import { - genericInternalError, - tenantKind, - TenantKind, -} from "pagopa-interop-models"; +import { tenantKind, TenantKind } from "pagopa-interop-models"; import { P, match } from "ts-pattern"; import { RiskAnalysisFormToValidate, @@ -17,6 +13,7 @@ import { RiskAnalysisValidationIssue, dependencyNotFoundError, expiredRulesVersionError, + incompatiblePersonalDataError, missingExpectedFieldError, rulesVersionNotFoundError, unexpectedDependencyValueError, @@ -24,6 +21,7 @@ import { unexpectedFieldFormatError, unexpectedFieldValueError, } from "./riskAnalysisValidationErrors.js"; + import { FormQuestionRules, RiskAnalysisFormRules, @@ -107,12 +105,16 @@ export function validateRiskAnalysis( .with("NO", () => false) .otherwise(() => undefined); - validatePersonalDataFlag({ + const personalDataFlagValidation = validatePersonalDataFlag({ tenantKind, version: formRulesForValidation.version, personalDataInRiskAnalysis, personalDataInEService, }); + + if (personalDataFlagValidation.length > 0) { + return invalidResult(personalDataFlagValidation); + } return validResult({ version: formRulesForValidation.version, singleAnswers, @@ -411,24 +413,25 @@ const validatePersonalDataFlag = ({ version: string; personalDataInRiskAnalysis: boolean | undefined; personalDataInEService: boolean | undefined; -}): void => { +}): RiskAnalysisValidationIssue[] => { const label = buildLabel(tenantKind, version); - match(label) + return match(label) .with( formRules.PA_1_0, formRules.PA_2_0, formRules.PA_3_0, formRules.PRIVATE_1_0, - () => void 0 + () => [] ) .with(formRules.PA_3_1, formRules.PRIVATE_2_0, () => match(personalDataInEService) .with(P.boolean, () => { if (personalDataInEService !== personalDataInRiskAnalysis) { - throw genericInternalError("Incompatible personalData flag"); + return [incompatiblePersonalDataError()]; } + return []; }) - .with(undefined, () => void 0) + .with(undefined, () => []) .exhaustive() ) .exhaustive(); diff --git a/packages/commons/src/risk-analysis/riskAnalysisValidationErrors.ts b/packages/commons/src/risk-analysis/riskAnalysisValidationErrors.ts index 97349222f4..d3b12fd948 100644 --- a/packages/commons/src/risk-analysis/riskAnalysisValidationErrors.ts +++ b/packages/commons/src/risk-analysis/riskAnalysisValidationErrors.ts @@ -8,7 +8,8 @@ type RiskAnalysisValidationIssueCode = | "dependencyNotFoundError" | "unexpectedDependencyValueError" | "unexpectedFieldFormatError" - | "missingExpectedFieldError"; + | "missingExpectedFieldError" + | "incompatiblePersonalDataError"; export class RiskAnalysisValidationIssue extends InternalError { constructor({ @@ -101,3 +102,10 @@ export function missingExpectedFieldError( detail: `Expected field ${fieldName} not found in form`, }); } + +export function incompatiblePersonalDataError(): RiskAnalysisValidationIssue { + return new RiskAnalysisValidationIssue({ + code: "incompatiblePersonalDataError", + detail: `The usesPersonalData answer doesn't match the personalData flag of the eservice`, + }); +} From 2f83f704abcfb6edcb616014f0ed75114557f238 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Tue, 14 Oct 2025 12:38:18 +0200 Subject: [PATCH 177/180] Add tests --- ...riskAnalysisValidation.integration.test.ts | 51 ++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/packages/commons-test/test/riskAnalysisValidation.integration.test.ts b/packages/commons-test/test/riskAnalysisValidation.integration.test.ts index 43fb9930e9..456f48e862 100644 --- a/packages/commons-test/test/riskAnalysisValidation.integration.test.ts +++ b/packages/commons-test/test/riskAnalysisValidation.integration.test.ts @@ -1,5 +1,4 @@ import { describe, expect, it, vi } from "vitest"; - import { RiskAnalysisFormToValidate, RiskAnalysisValidatedForm, @@ -11,6 +10,7 @@ import { validateRiskAnalysis, rulesVersionNotFoundError, expiredRulesVersionError, + incompatiblePersonalDataError, } from "pagopa-interop-commons"; import { tenantKind } from "pagopa-interop-models"; import { @@ -502,4 +502,53 @@ describe("Risk Analysis Validation", () => { ], }); }); + + it("should fail if the risk analysis is PRIVATE 2.0 and the eservice has different personalData", () => { + const riskAnalysisForm: RiskAnalysisFormToValidate = { + ...validRiskAnalysis2_0_Private, + answers: { + usesPersonalData: ["YES"], + ...validRiskAnalysis2_0_Private.answers, + }, + }; + expect( + validateRiskAnalysis(riskAnalysisForm, false, "GSP", new Date(), false) + ).toEqual({ + type: "invalid", + issues: [incompatiblePersonalDataError()], + }); + }); + + it("should succeed if the risk analysis is PRIVATE 2.0 and the eservice doesn't have the personalData flag", () => { + expect( + validateRiskAnalysis( + validRiskAnalysis2_0_Private, + false, + "GSP", + new Date(), + undefined + ) + ).toEqual({ + type: "valid", + value: validatedRiskAnalysis2_0_Private, + }); + }); + + it.each([true, false])( + "should succeed if the risk analysis is PA 3.0 and the eservice has any personalData flag", + (personalDataInEService) => { + expect( + validateRiskAnalysis( + validRiskAnalysis3_0_Pa, + false, + "PA", + new Date(), + personalDataInEService + ) + ).toEqual({ + type: "valid", + value: validatedRiskAnalysis3_0_Pa, + }); + } + ); }); From 97b19f80ba5075e0d283fa69febbc4f9542975b8 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 16 Oct 2025 12:27:03 +0200 Subject: [PATCH 178/180] Add new tests for 3.1 --- ...riskAnalysisValidation.integration.test.ts | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/packages/commons-test/test/riskAnalysisValidation.integration.test.ts b/packages/commons-test/test/riskAnalysisValidation.integration.test.ts index 456f48e862..8df9d560aa 100644 --- a/packages/commons-test/test/riskAnalysisValidation.integration.test.ts +++ b/packages/commons-test/test/riskAnalysisValidation.integration.test.ts @@ -551,4 +551,63 @@ describe("Risk Analysis Validation", () => { }); } ); + + it("should fail if the risk analysis is PA 3.1 and the eservice has different personalData", () => { + const riskAnalysisForm: RiskAnalysisFormToValidate = { + ...validRiskAnalysis3_1_Pa, + answers: { + ...validRiskAnalysis3_1_Pa.answers, + usesPersonalData: ["YES"], + }, + }; + expect( + validateRiskAnalysis(riskAnalysisForm, false, "PA", new Date(), false) + ).toEqual({ + type: "invalid", + issues: [incompatiblePersonalDataError()], + }); + }); + + it("should succeed if the risk analysis is PA 3.1 and the eservice doesn't have the personalData flag", () => { + expect( + validateRiskAnalysis( + validRiskAnalysis3_1_Pa, + false, + "PA", + new Date(), + undefined + ) + ).toEqual({ + type: "valid", + value: validatedRiskAnalysis3_1_Pa, + }); + }); + + it.each([ + { personalDataInEService: true, usesPersonalData: "YES" }, + { personalDataInEService: false, usesPersonalData: "NO" }, + ])( + "should succeed if the risk analysis is PA 3.1 and the eservice has consistent personalData flag", + ({ personalDataInEService, usesPersonalData }) => { + const riskAnalysisForm: RiskAnalysisFormToValidate = { + ...validRiskAnalysis3_1_Pa, + answers: { + ...validRiskAnalysis3_1_Pa.answers, + usesPersonalData: [usesPersonalData], + }, + }; + expect( + validateRiskAnalysis( + riskAnalysisForm, + false, + "PA", + new Date(), + personalDataInEService + ) + ).toEqual({ + type: "valid", + value: validatedRiskAnalysis3_1_Pa, + }); + } + ); }); From dc337107f3a9ad6cf11ea87fb733a2c2f56b739c Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 16 Oct 2025 12:27:09 +0200 Subject: [PATCH 179/180] Fix --- .../test/riskAnalysisValidation.integration.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/commons-test/test/riskAnalysisValidation.integration.test.ts b/packages/commons-test/test/riskAnalysisValidation.integration.test.ts index 8df9d560aa..1dfaee9eb0 100644 --- a/packages/commons-test/test/riskAnalysisValidation.integration.test.ts +++ b/packages/commons-test/test/riskAnalysisValidation.integration.test.ts @@ -507,8 +507,8 @@ describe("Risk Analysis Validation", () => { const riskAnalysisForm: RiskAnalysisFormToValidate = { ...validRiskAnalysis2_0_Private, answers: { - usesPersonalData: ["YES"], ...validRiskAnalysis2_0_Private.answers, + usesPersonalData: ["YES"], }, }; expect( From 16654f38db3191ca413c66f1fe0f3d61cc51ffc0 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 16 Oct 2025 16:31:08 +0200 Subject: [PATCH 180/180] Comment incomplete tests --- .../test/riskAnalysisValidation.integration.test.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/commons-test/test/riskAnalysisValidation.integration.test.ts b/packages/commons-test/test/riskAnalysisValidation.integration.test.ts index 1dfaee9eb0..88bc5bc6ff 100644 --- a/packages/commons-test/test/riskAnalysisValidation.integration.test.ts +++ b/packages/commons-test/test/riskAnalysisValidation.integration.test.ts @@ -552,6 +552,7 @@ describe("Risk Analysis Validation", () => { } ); + /* it("should fail if the risk analysis is PA 3.1 and the eservice has different personalData", () => { const riskAnalysisForm: RiskAnalysisFormToValidate = { ...validRiskAnalysis3_1_Pa, @@ -610,4 +611,5 @@ describe("Risk Analysis Validation", () => { }); } ); + */ });