Repository: pagopa/io-services-cms
Pull request #1228: [IOPAE-1918] functions ingestion activation
Author: login: leopoldo94
Labels: name: internal
name: changeset
name: webapp
name: infra
Created: 2025-04-08T14:05:13Z | Merged: 2025-04-10T09:25:04Z

<!--- Please always add a PR description as if nobody knows anything about the context these changes come from. -->
<!--- Even if we are all from our internal team, we may not be on the same page. -->
<!--- Write this PR as you were contributing to a public OSS project, where nobody knows you and you have to earn their trust. -->
<!--- This will improve our projects in the long run! Thanks. -->

#### List of Changes
[add generation client PDV](https://github.com/pagopa/io-services-cms/commit/13be0ad248b059223707d6f6a37caa0c97639fd0)
[avro schema formatter](https://github.com/pagopa/io-services-cms/commit/407052bc03ca80e96a936a995f35d774d46978d6)
[add pdv tokenizer](https://github.com/pagopa/io-services-cms/commit/15cf3e42e5ea3810bf754fc917eb03248a0c4ee1)
[add legacy activation model](https://github.com/pagopa/io-services-cms/commit/66cd6502dacb6aa6d7159ac60c0880fcc6108a66)
[implementation ingestion activations](https://github.com/pagopa/io-services-cms/commit/3589cbfa7b6221d204e9eba519431289048a0cbc)
[refactor ingestion services handlers](https://github.com/pagopa/io-services-cms/commit/f4c0888f6ef972b6b7e02da173af139640668d18)
[fix unit test after refactoring](https://github.com/pagopa/io-services-cms/commit/0161395030005e216a3882be8b2087d32ef73c23)
[infra ingestion activations and pdv](https://github.com/pagopa/io-services-cms/commit/dfee7a38cc919406961b14021e90c246ba1a62d2)
<!--- Describe your changes in detail -->

#### Motivation and Context
The necessity to ingest the activations of special services by users
<!--- Why is this change required? What problem does it solve? -->

#### How Has This Been Tested?
Local Env test
<!--- Please describe in detail how you tested your changes. -->
<!--- Include details of your testing environment, tests ran to see how -->
<!--- your change affects other areas of the code, etc. -->

#### Screenshots (if appropriate):

<!--- Attach screenshots in case changes impact UI. -->

#### Checklist:

<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->

- [ ] My change requires a change to the documentation.
- [ ] I have updated the documentation accordingly.



Diff:
diff --git a/.changeset/rare-snails-count.md b/.changeset/rare-snails-count.md
new file mode 100644
index 000000000..4f2945744
--- /dev/null
+++ b/.changeset/rare-snails-count.md
@@ -0,0 +1,6 @@
+---
+"@io-services-cms/models": patch
+"io-services-cms-webapp": patch
+---
+
+add ingestion activations
diff --git a/apps/io-services-cms-webapp/IngestionActivationWatcher/function.json b/apps/io-services-cms-webapp/IngestionActivationWatcher/function.json
new file mode 100644
index 000000000..d89fc99fd
--- /dev/null
+++ b/apps/io-services-cms-webapp/IngestionActivationWatcher/function.json
@@ -0,0 +1,26 @@
+{
+  "bindings": [
+    {
+      "authLevel": "function",
+      "type": "cosmosDBTrigger",
+      "direction": "in",
+      "name": "documents",
+      "connection": "LEGACY_COSMOSDB_CONNECTIONSTRING",
+      "databaseName": "%LEGACY_COSMOSDB_NAME%",
+      "containerName": "%LEGACY_COSMOSDB_CONTAINER_ACTIVATIONS%",
+      "leaseContainerName": "%LEGACY_COSMOSDB_CONTAINER_ACTIVATIONS_LEASE%-TEST",
+      "createLeaseContainerIfNotExists": true,
+      "startFromBeginning": true,
+      "maxItemsPerInvocation": 1
+    },
+    {
+      "queueName": "%REQUEST_ACTIVATIONS_INGESTION_RETRY_QUEUE%",
+      "connection": "INTERNAL_STORAGE_CONNECTION_STRING",
+      "name": "ingestionError",
+      "type": "queue",
+      "direction": "out"
+    }
+  ],
+  "scriptFile": "../dist/main.js",
+  "entryPoint": "onIngestionActivationChangeEntryPoint"
+}
diff --git a/apps/io-services-cms-webapp/OnRequestActivationIngestionRetry/function.json b/apps/io-services-cms-webapp/OnRequestActivationIngestionRetry/function.json
new file mode 100644
index 000000000..0bddfc466
--- /dev/null
+++ b/apps/io-services-cms-webapp/OnRequestActivationIngestionRetry/function.json
@@ -0,0 +1,13 @@
+{
+  "bindings": [
+    {
+      "queueName": "%REQUEST_ACTIVATIONS_INGESTION_RETRY_QUEUE%",
+      "connection": "INTERNAL_STORAGE_CONNECTION_STRING",
+      "name": "requestActivationIngestionRetryItem",
+      "type": "queueTrigger",
+      "direction": "in"
+    }
+  ],
+  "scriptFile": "../dist/main.js",
+  "entryPoint": "createRequestActivationIngestionRetryEntryPoint"
+}
diff --git a/apps/io-services-cms-webapp/avro/activation.json b/apps/io-services-cms-webapp/avro/activation.json
new file mode 100644
index 000000000..1cb3da28d
--- /dev/null
+++ b/apps/io-services-cms-webapp/avro/activation.json
@@ -0,0 +1,33 @@
+{
+  "name": "ServiceActivations",
+  "type": "record",
+  "namespace": "dto",
+  "doc": "Schema for 'service-activations'",
+  "fields": [
+    {
+      "name": "id",
+      "type": "string"
+    },
+    {
+      "name": "modifiedAt",
+      "type": "long",
+      "logicalType": "timestamp-millis"
+    },
+    {
+      "name": "userPDVId",
+      "type": "string"
+    },
+    {
+      "name": "serviceId",
+      "type": "string"
+    },
+    {
+      "name": "status",
+      "type": {
+        "type": "enum",
+        "name": "StatusEnum",
+        "symbols": ["ACTIVE", "INACTIVE", "PENDING"]
+      }
+    }
+  ]
+}
diff --git a/apps/io-services-cms-webapp/package.json b/apps/io-services-cms-webapp/package.json
index 48cf24fd0..9a3b50d45 100644
--- a/apps/io-services-cms-webapp/package.json
+++ b/apps/io-services-cms-webapp/package.json
@@ -20,7 +20,8 @@
     "lint:fix": "eslint --fix \"src/**\"",
     "start": "dotenv -e .env func start -- --javascript",
     "generate:avro": "rm -rf ./src/generated/avro && mkdir -p ./src/generated/avro && avro-to-typescript --compile ./avro ./src/generated/avro",
-    "generate:definitions": "rm -rf ./src/generated/api & gen-api-models --api-spec ./openapi.yaml --out-dir ./src/generated/api --request-types --response-decoders"
+    "generate:definitions": "rm -rf ./src/generated/api & gen-api-models --api-spec ./openapi.yaml --out-dir ./src/generated/api --request-types --response-decoders",
+    "generate:tokenizer-client": "rm -rf ./src/generated/pdv-tokenizer-api && gen-api-models --api-spec https://api.tokenizer.pdv.pagopa.it/docs/tokenizerpapis/openapi.json --out-dir ./src/generated/pdv-tokenizer-api --no-strict --request-types --response-decoders --client"
   },
   "devDependencies": {
     "@pagopa/eslint-config": "^4.0.1",
diff --git a/apps/io-services-cms-webapp/src/__tests__/main.test.ts b/apps/io-services-cms-webapp/src/__tests__/main.test.ts
index 3cdd2e2f9..26d0c82d3 100644
--- a/apps/io-services-cms-webapp/src/__tests__/main.test.ts
+++ b/apps/io-services-cms-webapp/src/__tests__/main.test.ts
@@ -110,8 +110,10 @@ const mocks = vi.hoisted(() => {
     createWebServer: vi.fn(() => {}),
     createServiceValidationHandler: vi.fn((...args: any[]) => {}),
     LegacyServiceCosmosResource: {},
+    LegacyActivation: {},
     processBatchOf: vi.fn().mockImplementation((...args) => () => {}),
     createRequestReviewHandler: vi.fn((...args: any[]) => {}),
+    createRequestActivationIngestionRetryHandler: vi.fn((...args: any[]) => {}),
     toAzureFunctionHandler: vi.fn(),
     setBindings: vi.fn((...args: any[]) => () => {}),
   };
@@ -194,6 +196,13 @@ vi.mock("../reviewer/request-review-handler", () => {
   };
 });
 
+vi.mock("../ingestion/request-activation-ingestion-retry-handler", () => {
+  return {
+    createRequestActivationIngestionRetryHandler:
+      mocks.createRequestActivationIngestionRetryHandler,
+  };
+});
+
 vi.mock("../watchers/on-selfcare-group-change", () => {
   return {
     makeHandler: mocks.makeHandler,
@@ -209,6 +218,7 @@ vi.mock("@io-services-cms/models", () => {
     stores: mocks.stores,
     ServiceHistory: mocks.ServiceHistory,
     LegacyServiceCosmosResource: mocks.LegacyServiceCosmosResource,
+    LegacyActivation: mocks.LegacyActivation,
   };
 });
 
diff --git a/apps/io-services-cms-webapp/src/config.ts b/apps/io-services-cms-webapp/src/config.ts
index 3e0bca588..eb5f9749a 100644
--- a/apps/io-services-cms-webapp/src/config.ts
+++ b/apps/io-services-cms-webapp/src/config.ts
@@ -277,43 +277,64 @@ export const ServicesHistoryEventHubConfig = t.type({
   SERVICES_HISTORY_EVENT_HUB_NAME: NonEmptyString,
 });
 
+export type ActivationEventHubConfig = t.TypeOf<
+  typeof ServicesHistoryEventHubConfig
+>;
+export const ActivationEventHubConfig = t.type({
+  ACTIVATIONS_EVENT_HUB_CONNECTION_STRING: NonEmptyString,
+  ACTIVATIONS_EVENT_HUB_NAME: NonEmptyString,
+});
+
+//PDV tokenizer client configuration
+export type PDVTokenizerClientConfiguration = t.TypeOf<
+  typeof PDVTokenizerClientConfiguration
+>;
+export const PDVTokenizerClientConfiguration = t.type({
+  PDV_TOKENIZER_API_KEY: NonEmptyString,
+  PDV_TOKENIZER_BASE_PATH: NonEmptyString,
+  PDV_TOKENIZER_BASE_URL: NonEmptyString,
+});
+
 // Global app configuration
 export type IConfig = t.TypeOf<typeof IConfig>;
 export const IConfig = t.intersection([
   t.intersection([
-    t.type({ isProduction: t.boolean }),
-    InternalStorageAccount,
-    JiraConfig,
-    ReviewerPostgreSqlConfig,
-    ServicePayloadConfig,
-  ]),
-  t.intersection([
-    CosmosConfig,
-    ApimUtils.definitions.AzureClientSecretCredential,
-    ApimConfig,
-    QueueConfig,
-    ServiceIdQualityCheckExclusionList,
-  ]),
-  t.intersection([
-    CosmosLegacyConfig,
-    PaginationConfig,
-    JiraLegacyProjectName,
-    ApplicationInsightConfig,
-    FeatureFlags,
-  ]),
-  t.intersection([
-    ExternalStorageAccountConfiguration,
-    BackofficeInternalSubnetCIDRs,
-    TopicPostgreSqlConfig,
-    ServiceValidationConfig,
-    DefaultValues,
-  ]),
-  t.intersection([
-    ServicesPublicationEventHubConfig,
-    ServicesTopicsEventHubConfig,
-    ServicesLifecycleEventHubConfig,
-    ServicesHistoryEventHubConfig,
+    t.intersection([
+      t.type({ isProduction: t.boolean }),
+      InternalStorageAccount,
+      JiraConfig,
+      ReviewerPostgreSqlConfig,
+      ServicePayloadConfig,
+    ]),
+    t.intersection([
+      CosmosConfig,
+      ApimUtils.definitions.AzureClientSecretCredential,
+      ApimConfig,
+      QueueConfig,
+      ServiceIdQualityCheckExclusionList,
+    ]),
+    t.intersection([
+      CosmosLegacyConfig,
+      PaginationConfig,
+      JiraLegacyProjectName,
+      ApplicationInsightConfig,
+      FeatureFlags,
+    ]),
+    t.intersection([
+      ExternalStorageAccountConfiguration,
+      BackofficeInternalSubnetCIDRs,
+      TopicPostgreSqlConfig,
+      ServiceValidationConfig,
+      DefaultValues,
+    ]),
+    t.intersection([
+      ServicesPublicationEventHubConfig,
+      ServicesTopicsEventHubConfig,
+      ServicesLifecycleEventHubConfig,
+      ServicesHistoryEventHubConfig,
+    ]),
   ]),
+  t.intersection([PDVTokenizerClientConfiguration, ActivationEventHubConfig]),
 ]);
 
 export const envConfig = {
diff --git a/apps/io-services-cms-webapp/src/ingestion/request-activation-ingestion-retry-handler.ts b/apps/io-services-cms-webapp/src/ingestion/request-activation-ingestion-retry-handler.ts
new file mode 100644
index 000000000..3703b9d0a
--- /dev/null
+++ b/apps/io-services-cms-webapp/src/ingestion/request-activation-ingestion-retry-handler.ts
@@ -0,0 +1,48 @@
+import { EventHubProducerClient } from "@azure/event-hubs";
+import { LegacyActivation } from "@io-services-cms/models";
+import * as TE from "fp-ts/lib/TaskEither";
+import * as t from "io-ts";
+
+import { withJsonInput } from "../lib/azure/misc";
+import { EnrichedLegacyActivationCosmosResource } from "../utils/ingestion/enriched-types/activation-pdv-enriched";
+import { enricher } from "../utils/ingestion/enricher/pdv-enricher";
+import { avroActivationFormatter } from "../utils/ingestion/formatter/activation-avro-formatter";
+import { createIngestionRetryQueueTriggerHandler } from "../utils/ingestion/ingestion-handlers";
+import { PdvTokenizerClient } from "../utils/pdvTokenizerClient";
+
+const isEnrichedLegacyActivation = (
+  item:
+    | EnrichedLegacyActivationCosmosResource
+    | LegacyActivation.CosmosResource,
+): item is EnrichedLegacyActivationCosmosResource => "userPDVId" in item;
+
+export const createRequestActivationIngestionRetryHandler = (
+  producer: EventHubProducerClient,
+  pdvTokenizerClient: PdvTokenizerClient,
+): ReturnType<typeof withJsonInput> => {
+  const ActivationResourceDecoder = t.union([
+    EnrichedLegacyActivationCosmosResource,
+    LegacyActivation.CosmosResource,
+  ]);
+
+  const conditionalEnricher = (
+    item:
+      | EnrichedLegacyActivationCosmosResource
+      | LegacyActivation.CosmosResource,
+  ): TE.TaskEither<Error, EnrichedLegacyActivationCosmosResource> => {
+    if (isEnrichedLegacyActivation(item)) {
+      return TE.right(item);
+    } else {
+      return enricher<LegacyActivation.CosmosResource>(pdvTokenizerClient)(
+        item,
+      );
+    }
+  };
+
+  return createIngestionRetryQueueTriggerHandler(
+    ActivationResourceDecoder,
+    producer,
+    avroActivationFormatter,
+    conditionalEnricher,
+  );
+};
diff --git a/apps/io-services-cms-webapp/src/ingestion/service-topic-ingestor-handler.ts b/apps/io-services-cms-webapp/src/ingestion/service-topic-ingestor-handler.ts
index effacf341..844a47b71 100644
--- a/apps/io-services-cms-webapp/src/ingestion/service-topic-ingestor-handler.ts
+++ b/apps/io-services-cms-webapp/src/ingestion/service-topic-ingestor-handler.ts
@@ -23,7 +23,6 @@ const writeTopicsOnEventHub = (
   return pipe(
     items,
     toEvents(avroServiceTopicFormatter),
-    TE.fromEither,
     TE.chainW(
       (events) => TE.tryCatch(() => producer.sendBatch(events), E.toError), // send the formatted service to the eventhub
     ),
diff --git a/apps/io-services-cms-webapp/src/main.ts b/apps/io-services-cms-webapp/src/main.ts
index a5c939812..880701350 100644
--- a/apps/io-services-cms-webapp/src/main.ts
+++ b/apps/io-services-cms-webapp/src/main.ts
@@ -2,6 +2,7 @@ import { EventHubProducerClient } from "@azure/event-hubs";
 import { AzureFunction } from "@azure/functions";
 import { ApimUtils } from "@io-services-cms/external-clients";
 import {
+  LegacyActivation,
   LegacyServiceCosmosResource,
   ServiceHistory,
   ServiceLifecycle,
@@ -31,6 +32,7 @@ import { getConfigOrThrow } from "./config";
 import { createRequestDeletionHandler } from "./deletor/request-deletion-handler";
 import { createRequestDetailHandler } from "./detailRequestor/request-detail-handler";
 import { createRequestHistoricizationHandler } from "./historicizer/request-historicization-handler";
+import { createRequestActivationIngestionRetryHandler } from "./ingestion/request-activation-ingestion-retry-handler";
 import { createRequestServicesHistoryIngestionRetryHandler } from "./ingestion/request-services-history-ingestion-retry-handler";
 import { createRequestServicesLifecycleIngestionRetryHandler } from "./ingestion/request-services-lifecycle-ingestion-retry-handler";
 import { createRequestServicesPublicationIngestionRetryHandler } from "./ingestion/request-services-publication-ingestion-retry-handler";
@@ -64,10 +66,13 @@ import {
   cosmosdbClient,
   cosmosdbInstance as legacyCosmosDbInstance,
 } from "./utils/cosmos-legacy";
+import { httpOrHttpsApiFetch } from "./utils/fetch";
 import { jiraProxy } from "./utils/jira-proxy";
+import { pdvTokenizerClient } from "./utils/pdvTokenizerClient";
 import { getDao as getServiceReviewDao } from "./utils/service-review-dao";
 import { getDao as getServiceTopicDao } from "./utils/service-topic-dao";
 import { GroupChangeEvent } from "./utils/sync-group-utils";
+import { handler as onIngestionActivationChangeHandler } from "./watchers/on-activation-ingestion-change";
 import { handler as onLegacyServiceChangeHandler } from "./watchers/on-legacy-service-change";
 import { makeHandler as makeOnSelfcareGroupChangeHandler } from "./watchers/on-selfcare-group-change";
 import { handler as onServiceDetailLifecycleChangeHandler } from "./watchers/on-service-detail-lifecycle-change";
@@ -152,6 +157,14 @@ const fsmPublicationClient = ServicePublication.getFsmClient(
   servicePublicationStore,
 );
 
+// PDV tokenizer Client
+const pdvTokenizer = pdvTokenizerClient(
+  config.PDV_TOKENIZER_BASE_URL,
+  config.PDV_TOKENIZER_API_KEY,
+  httpOrHttpsApiFetch,
+  config.PDV_TOKENIZER_BASE_PATH,
+);
+
 // AppInsights client for Telemetry
 const telemetryClient = initTelemetryClient(
   config.APPLICATIONINSIGHTS_CONNECTION_STRING,
@@ -189,6 +202,12 @@ const serviceHistoryEventHubProducer = new EventHubProducerClient(
   config.SERVICES_HISTORY_EVENT_HUB_NAME,
 );
 
+// eventhub producer for Activations
+const activationEventHubProducer = new EventHubProducerClient(
+  config.ACTIVATIONS_EVENT_HUB_CONNECTION_STRING,
+  config.ACTIVATIONS_EVENT_HUB_NAME,
+);
+
 // entrypoint for all http functions
 export const httpEntryPoint = pipe(
   {
@@ -478,6 +497,21 @@ export const onIngestionServiceHistoryChangeEntryPoint = pipe(
   toAzureFunctionHandler,
 );
 
+//Ingestion Activations
+export const onIngestionActivationChangeEntryPoint = pipe(
+  onIngestionActivationChangeHandler(activationEventHubProducer, pdvTokenizer),
+  processAllOf(LegacyActivation.CosmosResource),
+  setBindings((results) => ({
+    ingestionError: pipe(
+      results,
+      RA.map(RR.lookup("ingestionError")),
+      RA.filter(O.isSome),
+      RA.map((item) => pipe(item.value, JSON.stringify)),
+    ),
+  })),
+  toAzureFunctionHandler,
+);
+
 //Ingestion Service Lifecycle Retry DLQ
 export const createRequestServicesLifecycleIngestionRetryEntryPoint =
   createRequestServicesLifecycleIngestionRetryHandler(
@@ -488,3 +522,9 @@ export const createRequestServicesHistoryIngestionRetryEntryPoint =
   createRequestServicesHistoryIngestionRetryHandler(
     serviceHistoryEventHubProducer,
   );
+//Ingestion Activation Retry DLQ
+export const createRequestActivationIngestionRetryEntryPoint =
+  createRequestActivationIngestionRetryHandler(
+    activationEventHubProducer,
+    pdvTokenizer,
+  );
diff --git a/apps/io-services-cms-webapp/src/utils/fetch.ts b/apps/io-services-cms-webapp/src/utils/fetch.ts
new file mode 100644
index 000000000..352145597
--- /dev/null
+++ b/apps/io-services-cms-webapp/src/utils/fetch.ts
@@ -0,0 +1,19 @@
+import { agent } from "@pagopa/ts-commons";
+import {
+  AbortableFetch,
+  setFetchTimeout,
+  toFetch,
+} from "@pagopa/ts-commons/lib/fetch";
+import { Millisecond } from "@pagopa/ts-commons/lib/units";
+
+export const DEFAULT_REQUEST_TIMEOUT_MS = 10000 as Millisecond;
+
+// Generic HTTP/HTTPS fetch with optional keepalive agent
+// @see https://github.com/pagopa/io-ts-commons/blob/master/src/agent.ts#L10
+const abortableFetch = AbortableFetch(agent.getFetch(process.env));
+const fetchWithTimeout = setFetchTimeout(
+  DEFAULT_REQUEST_TIMEOUT_MS,
+  abortableFetch,
+);
+
+export const httpOrHttpsApiFetch = toFetch(fetchWithTimeout);
diff --git a/apps/io-services-cms-webapp/src/utils/ingestion/__tests__/ingestion-handlers.test.ts b/apps/io-services-cms-webapp/src/utils/ingestion/__tests__/ingestion-handlers.test.ts
index c37e34753..c7604a3e0 100644
--- a/apps/io-services-cms-webapp/src/utils/ingestion/__tests__/ingestion-handlers.test.ts
+++ b/apps/io-services-cms-webapp/src/utils/ingestion/__tests__/ingestion-handlers.test.ts
@@ -1,7 +1,9 @@
 import { EventHubProducerClient } from "@azure/event-hubs";
 import { Context } from "@azure/functions";
 import * as E from "fp-ts/lib/Either";
+import * as TE from "fp-ts/lib/TaskEither";
 import * as t from "io-ts";
+import { pipe } from "fp-ts/lib/function";
 import { Json } from "io-ts-types";
 import { afterEach, describe, expect, it, vi } from "vitest";
 import {
diff --git a/apps/io-services-cms-webapp/src/utils/ingestion/enriched-types/activation-pdv-enriched.ts b/apps/io-services-cms-webapp/src/utils/ingestion/enriched-types/activation-pdv-enriched.ts
new file mode 100644
index 000000000..9f7dfa6bc
--- /dev/null
+++ b/apps/io-services-cms-webapp/src/utils/ingestion/enriched-types/activation-pdv-enriched.ts
@@ -0,0 +1,13 @@
+import { LegacyActivation } from "@io-services-cms/models";
+import * as t from "io-ts";
+
+export const EnrichedLegacyActivationCosmosResource: t.IntersectionType<
+  [typeof LegacyActivation.CosmosResource, t.TypeC<{ userPDVId: t.StringC }>]
+> = t.intersection([
+  LegacyActivation.CosmosResource,
+  t.type({ userPDVId: t.string }),
+]);
+
+export type EnrichedLegacyActivationCosmosResource = t.TypeOf<
+  typeof EnrichedLegacyActivationCosmosResource
+>;
diff --git a/apps/io-services-cms-webapp/src/utils/ingestion/enricher/pdv-enricher.ts b/apps/io-services-cms-webapp/src/utils/ingestion/enricher/pdv-enricher.ts
new file mode 100644
index 000000000..05b5987fa
--- /dev/null
+++ b/apps/io-services-cms-webapp/src/utils/ingestion/enricher/pdv-enricher.ts
@@ -0,0 +1,58 @@
+import { readableReportSimplified } from "@pagopa/ts-commons/lib/reporters";
+import * as E from "fp-ts/lib/Either";
+import * as RTE from "fp-ts/lib/ReaderTaskEither";
+import * as TE from "fp-ts/lib/TaskEither";
+import { flow, pipe } from "fp-ts/lib/function";
+import { NonEmptyString } from "io-ts-types/lib/NonEmptyString";
+
+import { PdvTokenizerClient } from "../../pdvTokenizerClient";
+
+export const enricher =
+  <T extends { fiscalCode: string }>(
+    pdvTokenizerClient: PdvTokenizerClient,
+  ): RTE.ReaderTaskEither<
+    T,
+    Error,
+    {
+      userPDVId: NonEmptyString;
+    } & T
+  > =>
+  (item: T) =>
+    pipe(
+      TE.tryCatch(
+        () =>
+          pdvTokenizerClient.saveUsingPUT({
+            body: { pii: item.fiscalCode },
+          }),
+        E.toError,
+      ),
+      TE.chainEitherKW(
+        E.mapLeft((errors) => Error(readableReportSimplified(errors))),
+      ),
+      TE.chain((pdvResponse) =>
+        pdvResponse.status === 200
+          ? TE.right<Error, string>(pdvResponse.value.token)
+          : TE.left(
+              Error(
+                `Pdv tokenizer returned ${pdvResponse.status} with error: ${pdvResponse.value?.title}`,
+              ),
+            ),
+      ),
+      TE.chain(
+        flow(
+          NonEmptyString.decode,
+          TE.fromEither,
+          TE.mapLeft((errors) =>
+            Error(
+              `Unexpected empty token from tokenizer: ${readableReportSimplified(
+                errors,
+              )}`,
+            ),
+          ),
+        ),
+      ),
+      TE.map((userPDVId) => ({
+        ...item,
+        userPDVId,
+      })),
+    );
diff --git a/apps/io-services-cms-webapp/src/utils/ingestion/formatter/activation-avro-formatter.ts b/apps/io-services-cms-webapp/src/utils/ingestion/formatter/activation-avro-formatter.ts
new file mode 100644
index 000000000..b70e2efcb
--- /dev/null
+++ b/apps/io-services-cms-webapp/src/utils/ingestion/formatter/activation-avro-formatter.ts
@@ -0,0 +1,39 @@
+import { EventData } from "@azure/event-hubs";
+import * as avro from "avsc";
+import * as E from "fp-ts/lib/Either";
+import { pipe } from "fp-ts/lib/function";
+
+import { ServiceActivations as avroActivation } from "../../../generated/avro/dto/ServiceActivations";
+import { EnrichedLegacyActivationCosmosResource } from "../enriched-types/activation-pdv-enriched";
+
+export const buildAvroActivationObject = (
+  activationCosmosRecord: EnrichedLegacyActivationCosmosResource,
+): Omit<avroActivation, "schema" | "subject"> => ({
+  id: [
+    activationCosmosRecord.userPDVId,
+    activationCosmosRecord.serviceId,
+    activationCosmosRecord._ts,
+  ].join("-"),
+  modifiedAt: activationCosmosRecord._ts,
+  serviceId: activationCosmosRecord.serviceId,
+  status: activationCosmosRecord.status,
+  userPDVId: activationCosmosRecord.userPDVId,
+});
+
+export const avroActivationFormatter = (
+  item: EnrichedLegacyActivationCosmosResource,
+): E.Either<Error, EventData> =>
+  pipe(
+    Object.assign(new avroActivation(), buildAvroActivationObject(item)),
+    E.right,
+    E.chain((avroObj) =>
+      E.tryCatch(
+        () =>
+          avro.Type.forSchema(
+            avroActivation.schema as avro.Schema, // cast due to tsc can not proper recognize object as avro.Schema (eg. if you use const schemaServices: avro.Type = JSON.parse(JSON.stringify(services.schema())); it will loose the object type and it will work fine)
+          ).toBuffer(avroObj),
+        E.toError,
+      ),
+    ),
+    E.map((avroBuffer) => ({ body: avroBuffer })),
+  );
diff --git a/apps/io-services-cms-webapp/src/utils/ingestion/ingestion-handlers.ts b/apps/io-services-cms-webapp/src/utils/ingestion/ingestion-handlers.ts
index 52047eac2..1d768fda6 100644
--- a/apps/io-services-cms-webapp/src/utils/ingestion/ingestion-handlers.ts
+++ b/apps/io-services-cms-webapp/src/utils/ingestion/ingestion-handlers.ts
@@ -1,10 +1,11 @@
 import { EventData, EventHubProducerClient } from "@azure/event-hubs";
 import * as A from "fp-ts/lib/Array";
 import * as E from "fp-ts/lib/Either";
+import * as RE from "fp-ts/lib/ReaderEither";
 import * as RTE from "fp-ts/lib/ReaderTaskEither";
 import * as T from "fp-ts/lib/Task";
 import * as TE from "fp-ts/lib/TaskEither";
-import { pipe } from "fp-ts/lib/function";
+import { flow, pipe } from "fp-ts/lib/function";
 import * as t from "io-ts";
 
 import { withJsonInput } from "../../lib/azure/misc";
@@ -21,16 +22,27 @@ export type IngestionResults<S> = IngestionError<S> | IngestionSuccess;
 
 const noAction = {};
 
+const noEnricher = <S, U extends S>(item: S) => TE.right(item as U);
+
 export const toEvents =
-  <S>(formatter: (item: S) => E.Either<Error, EventData>) =>
-  (items: readonly S[]): E.Either<Error, EventData[]> =>
-    pipe([...items], A.traverse(E.Applicative)(formatter));
+  <S, U extends S>(
+    formatter: RE.ReaderEither<U, Error, EventData>,
+    enricher: RTE.ReaderTaskEither<S, Error, U> = noEnricher,
+  ) =>
+  (items: readonly S[]): TE.TaskEither<Error, EventData[]> =>
+    pipe(
+      [...items],
+      A.traverse(TE.ApplicativeSeq)((item) =>
+        pipe(item, enricher, TE.chainEitherK(formatter)),
+      ),
+    );
 
 // CosmosDBTrigger
 export const createIngestionCosmosDBTriggerHandler =
-  <S>(
+  <S, U extends S>(
     producer: EventHubProducerClient,
-    formatter: (item: S) => E.Either<Error, EventData>,
+    formatter: RE.ReaderEither<U, Error, EventData>,
+    enricher: RTE.ReaderTaskEither<S, Error, U> = noEnricher,
   ): RTE.ReaderTaskEither<
     { items: readonly S[] },
     never,
@@ -39,8 +51,7 @@ export const createIngestionCosmosDBTriggerHandler =
   ({ items }) =>
     pipe(
       items,
-      toEvents(formatter), // format service to the specified avro format
-      TE.fromEither,
+      toEvents(formatter, enricher), // format service to the specified avro format
       TE.chainW(
         (events) => TE.tryCatch(() => producer.sendBatch(events), E.toError), // send the formatted service to the eventhub
       ),
@@ -57,19 +68,21 @@ export const createIngestionCosmosDBTriggerHandler =
     );
 
 // Retry QuqueTrigger
-export const createIngestionRetryQueueTriggerHandler = <S>(
+export const createIngestionRetryQueueTriggerHandler = <S, U extends S>(
   decoder: t.Decoder<unknown, S>, // parse the incoming message
   producer: EventHubProducerClient,
-  formatter: (item: S) => E.Either<Error, EventData>,
+  formatter: (item: S) => E.Either<Error, EventData>, //TaskEither to support async enrichment
+  enricher: RTE.ReaderTaskEither<S, Error, U> = noEnricher,
 ): ReturnType<typeof withJsonInput> =>
   withJsonInput((context, queueItem) =>
     pipe(
       queueItem,
       parseIncomingMessage(decoder),
-      E.chainW(formatter),
       TE.fromEither,
-      TE.chainW(
-        (event) => TE.tryCatch(() => producer.sendBatch([event]), E.toError), // send the formatted service to the eventhub
+      TE.chainW(enricher),
+      TE.chainW(flow(formatter, TE.fromEither)),
+      TE.chainW((event) =>
+        TE.tryCatch(() => producer.sendBatch([event]), E.toError),
       ),
       TE.fold(
         (e) => {
diff --git a/apps/io-services-cms-webapp/src/utils/pdvTokenizerClient.ts b/apps/io-services-cms-webapp/src/utils/pdvTokenizerClient.ts
new file mode 100644
index 000000000..d8e22f5a6
--- /dev/null
+++ b/apps/io-services-cms-webapp/src/utils/pdvTokenizerClient.ts
@@ -0,0 +1,29 @@
+import { Client, createClient } from "../generated/pdv-tokenizer-api/client";
+
+export const pdvTokenizerClient = (
+  baseUrl: string,
+  token: string,
+  fetchApi: typeof fetch = fetch as unknown as typeof fetch,
+  basePath: string,
+): Client<"api_key"> =>
+  createClient<"api_key">({
+    basePath,
+    baseUrl,
+    fetchApi,
+    withDefaults:
+      (
+        // NOTE: cast to any necessary because the codegen does not aggregate well all request types,
+        // requiring a mandatory body in all requests in this case(please refer to issue #329)
+        // eslint-disable-next-line @typescript-eslint/no-explicit-any
+        op: any,
+        // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
+      ) =>
+      (params) =>
+        op({
+          ...params,
+          // please refer to source api spec for actual header mapping
+          api_key: token,
+        }),
+  });
+
+export type PdvTokenizerClient = ReturnType<typeof pdvTokenizerClient>;
diff --git a/apps/io-services-cms-webapp/src/watchers/on-activation-ingestion-change.ts b/apps/io-services-cms-webapp/src/watchers/on-activation-ingestion-change.ts
new file mode 100644
index 000000000..be4bc3e0c
--- /dev/null
+++ b/apps/io-services-cms-webapp/src/watchers/on-activation-ingestion-change.ts
@@ -0,0 +1,28 @@
+import { EventHubProducerClient } from "@azure/event-hubs";
+import { LegacyActivation } from "@io-services-cms/models";
+import * as RTE from "fp-ts/lib/ReaderTaskEither";
+
+import { EnrichedLegacyActivationCosmosResource } from "../utils/ingestion/enriched-types/activation-pdv-enriched";
+import { enricher } from "../utils/ingestion/enricher/pdv-enricher";
+import { avroActivationFormatter } from "../utils/ingestion/formatter/activation-avro-formatter";
+import {
+  IngestionResults,
+  createIngestionCosmosDBTriggerHandler,
+} from "../utils/ingestion/ingestion-handlers";
+import { PdvTokenizerClient } from "../utils/pdvTokenizerClient";
+
+export const handler = (
+  producer: EventHubProducerClient,
+  pdvTokenizerClient: PdvTokenizerClient,
+): RTE.ReaderTaskEither<
+  {
+    items: readonly LegacyActivation.CosmosResource[];
+  },
+  never,
+  IngestionResults<EnrichedLegacyActivationCosmosResource>[]
+> =>
+  createIngestionCosmosDBTriggerHandler(
+    producer,
+    avroActivationFormatter,
+    enricher<LegacyActivation.CosmosResource>(pdvTokenizerClient),
+  );
diff --git a/apps/io-services-cms-webapp/turbo.json b/apps/io-services-cms-webapp/turbo.json
index 9360b0ee5..2003e0a09 100644
--- a/apps/io-services-cms-webapp/turbo.json
+++ b/apps/io-services-cms-webapp/turbo.json
@@ -1,30 +1,26 @@
 {
-  "extends": [
-    "//"
-  ],
+  "extends": ["//"],
   "tasks": {
+    "generate:tokenizer-client": {
+      "outputs": ["src/generated/pdv-tokenizer-api/*"]
+    },
     "generate:definitions": {
       "inputs": [
         "openapi.yaml",
         "../../packages/io-services-cms-models/openapi/*.yaml"
       ],
-      "outputs": [
-        "src/generated/api/**/*"
-      ]
+      "outputs": ["src/generated/api/**/*"]
     },
     "generate:avro": {
-      "inputs": [
-        "avro/**"
-      ],
-      "outputs": [
-        "src/generated/avro/**/*"
-      ]
+      "inputs": ["avro/**"],
+      "outputs": ["src/generated/avro/**/*"]
     },
     "generate": {
       "dependsOn": [
         "generate:definitions",
-        "generate:avro"
+        "generate:avro",
+        "generate:tokenizer-client"
       ]
     }
   }
-}
\ No newline at end of file
+}
diff --git a/infra/resources/_modules/cms_function_app/README.md b/infra/resources/_modules/cms_function_app/README.md
index 563b3ede4..0d6736a65 100644
--- a/infra/resources/_modules/cms_function_app/README.md
+++ b/infra/resources/_modules/cms_function_app/README.md
@@ -66,6 +66,7 @@ No requirements.
 | [azurerm_key_vault_secret.jira_token](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/key_vault_secret) | data source |
 | [azurerm_key_vault_secret.legacy_cosmosdb_connectionstring](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/key_vault_secret) | data source |
 | [azurerm_key_vault_secret.legacy_cosmosdb_key](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/key_vault_secret) | data source |
+| [azurerm_key_vault_secret.pdv_tokenizer_api_key](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/key_vault_secret) | data source |
 | [azurerm_key_vault_secret.pgres_flex_reviewer_usr_pwd](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/key_vault_secret) | data source |
 | [azurerm_key_vault_secret.serviceid_quality_check_exclusion_list](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/key_vault_secret) | data source |
 | [azurerm_key_vault_secret.services_history_event_hub_connection_string](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/key_vault_secret) | data source |
diff --git a/infra/resources/_modules/cms_function_app/data.tf b/infra/resources/_modules/cms_function_app/data.tf
index 62bbd755a..fed1fb052 100644
--- a/infra/resources/_modules/cms_function_app/data.tf
+++ b/infra/resources/_modules/cms_function_app/data.tf
@@ -117,3 +117,8 @@ data "azurerm_private_dns_zone" "storage_account_queue" {
   name                = "privatelink.queue.core.windows.net"
   resource_group_name = var.private_dns_zone_resource_group_name
 }
+
+data "azurerm_key_vault_secret" "pdv_tokenizer_api_key" {
+  name         = "PDV-TOKENIZER-API-KEY"
+  key_vault_id = data.azurerm_key_vault.cms_key_vault.id
+}
diff --git a/infra/resources/_modules/cms_function_app/locals.tf b/infra/resources/_modules/cms_function_app/locals.tf
index ea45e7ac4..0d7bf7814 100644
--- a/infra/resources/_modules/cms_function_app/locals.tf
+++ b/infra/resources/_modules/cms_function_app/locals.tf
@@ -69,7 +69,9 @@ locals {
       LEGACY_COSMOSDB_URI                             = data.azurerm_cosmosdb_account.cosmos_legacy.endpoint
       LEGACY_COSMOSDB_KEY                             = data.azurerm_key_vault_secret.legacy_cosmosdb_key.value
       LEGACY_COSMOSDB_CONTAINER_SERVICES              = "services"
+      LEGACY_COSMOSDB_CONTAINER_ACTIVATIONS           = "activations"
       LEGACY_COSMOSDB_CONTAINER_SERVICES_LEASE        = "services-cms--legacy-watcher-lease"
+      LEGACY_COSMOSDB_CONTAINER_ACTIVATIONS_LEASE     = "activations-ingestion-lease"
       LEGACY_SERVICE_WATCHER_MAX_ITEMS_PER_INVOCATION = 10
 
       // Internal Storage Account Queues
@@ -131,6 +133,12 @@ locals {
       EH_SC_CONNECTIONSTRING         = data.azurerm_key_vault_secret.eh_sc_connectionstring.value
       EH_SC_USERGROUP_NAME           = "sc-usergroups"
       EH_SC_USERGROUP_CONSUMER_GROUP = "io-cms-sync"
+
+      # PDV configurations
+      PDV_TOKENIZER_BASE_URL  = "https://api.tokenizer.pdv.pagopa.it"
+      PDV_TOKENIZER_BASE_PATH = "/tokenizer/v1"
+      PDV_TOKENIZER_API_KEY   = "@Microsoft.KeyVault(VaultName=${data.azurerm_key_vault.cms_key_vault.name};SecretName=PDV-TOKENIZER-API-KEY)"
+
     }
     autoscale_settings = {
       min     = 3
diff --git a/infra/resources/_modules/cms_function_app/main.tf b/infra/resources/_modules/cms_function_app/main.tf
index 76ddf6bfa..d5f3f6173 100644
--- a/infra/resources/_modules/cms_function_app/main.tf
+++ b/infra/resources/_modules/cms_function_app/main.tf
@@ -58,6 +58,9 @@ module "cms_fn" {
       "AzureWebJobs.OnRequestServicesHistoryIngestionRetry.Disabled"     = "0"
       "AzureWebJobs.ServiceTopicsIngestor.Disabled"                      = "0"
       "AzureWebJobs.SelfcareGroupWatcher.Disabled"                       = "0"
+      "AzureWebJobs.IngestionActivationWatcher.Disabled"                 = "1"
+      "AzureWebJobs.OnRequestActivationIngestionRetry.Disabled"          = "1"
+
     }
   )
 
@@ -89,6 +92,8 @@ module "cms_fn" {
       "AzureWebJobs.OnRequestServicesHistoryIngestionRetry.Disabled"     = "1"
       "AzureWebJobs.ServiceTopicsIngestor.Disabled"                      = "1"
       "AzureWebJobs.SelfcareGroupWatcher.Disabled"                       = "1"
+      "AzureWebJobs.IngestionActivationWatcher.Disabled"                 = "1"
+      "AzureWebJobs.OnRequestActivationIngestionRetry.Disabled"          = "1"
     }
   )
 
@@ -117,7 +122,9 @@ module "cms_fn" {
     "AzureWebJobs.IngestionServiceHistoryWatcher.Disabled",
     "AzureWebJobs.OnRequestServicesHistoryIngestionRetry.Disabled",
     "AzureWebJobs.ServiceTopicsIngestor.Disabled",
-    "AzureWebJobs.SelfcareGroupWatcher.Disabled"
+    "AzureWebJobs.SelfcareGroupWatcher.Disabled",
+    "AzureWebJobs.IngestionActivationWatcher.Disabled",
+    "AzureWebJobs.OnRequestActivationIngestionRetry.Disabled",
   ]
 
   tier = local.cms.tier
diff --git a/packages/io-services-cms-models/src/activation-legacy/index.ts b/packages/io-services-cms-models/src/activation-legacy/index.ts
new file mode 100644
index 000000000..be40d33f7
--- /dev/null
+++ b/packages/io-services-cms-models/src/activation-legacy/index.ts
@@ -0,0 +1,16 @@
+import { Activation } from "@pagopa/io-functions-commons/dist/src/models/activation";
+import * as t from "io-ts";
+
+export const LegacyActivation = t.intersection([
+  Activation,
+  t.type({ version: t.number }),
+]);
+
+export type LegacyActivation = t.TypeOf<typeof LegacyActivation>;
+
+export const CosmosResource = t.intersection([
+  LegacyActivation,
+  t.type({ _ts: t.Integer }),
+]);
+
+export type CosmosResource = t.TypeOf<typeof CosmosResource>;
diff --git a/packages/io-services-cms-models/src/index.ts b/packages/io-services-cms-models/src/index.ts
index 6751abcc3..249a7ef46 100644
--- a/packages/io-services-cms-models/src/index.ts
+++ b/packages/io-services-cms-models/src/index.ts
@@ -1,3 +1,4 @@
+export * as LegacyActivation from "./activation-legacy";
 export {
   FSMStore,
   FsmAuthorizationError,


Reviews:
user: login: rodoviti
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T16:12:35Z
user: login: rodoviti
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T16:43:40Z
user: login: rodoviti
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T16:51:12Z
user: login: rodoviti
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T09:05:27Z

Review comments:
diff_hunk: @@ -131,6 +133,12 @@ locals {
       EH_SC_CONNECTIONSTRING         = data.azurerm_key_vault_secret.eh_sc_connectionstring.value
       EH_SC_USERGROUP_NAME           = "sc-usergroups"
       EH_SC_USERGROUP_CONSUMER_GROUP = "io-cms-sync"
+
+      # PDV configurations
+      PDV_TOKENIZER_BASE_URL  = "https://api.tokenizer.pdv.pagopa.it"
+      PDV_TOKENIZER_BASE_PATH = "/tokenizer/v1"
+      # PDV_TOKENIZER_API_KEY=data.azurerm_key_vault_secret.pdv_tokenizer_api_key.value
path: infra/resources/_modules/cms_function_app/locals.tf
user: login: rodoviti
body: ```suggestion
      # PDV_TOKENIZER_API_KEY="@Microsoft.KeyVault(VaultName=${data.azurerm_key_vault.cms_key_vault.name};SecretName=${data. azurerm_key_vault_secret.pdv_tokenizer_api_key.name})"
```
created_at: 2025-04-09T16:12:34Z
author_association: CONTRIBUTOR
diff_hunk: @@ -22,15 +23,24 @@ export type IngestionResults<S> = IngestionError<S> | IngestionSuccess;
 const noAction = {};
 
 export const toEvents =
-  <S>(formatter: (item: S) => E.Either<Error, EventData>) =>
-  (items: readonly S[]): E.Either<Error, EventData[]> =>
-    pipe([...items], A.traverse(E.Applicative)(formatter));
+  <S, U extends S>(
+    formatter: RE.ReaderEither<U, Error, EventData>,
+    enricher: RTE.ReaderTaskEither<S, Error, U> = (item) => TE.right(item as U),
path: apps/io-services-cms-webapp/src/utils/ingestion/ingestion-handlers.ts
user: login: rodoviti
body: suggestion: define a constant for the default enricher `(item) => TE.right(item as U)` (such as `noEnricher` or something like that)
created_at: 2025-04-09T16:43:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,38 @@
+import { EventData } from "@azure/event-hubs";
+import * as avro from "avsc";
+import * as E from "fp-ts/lib/Either";
+import { pipe } from "fp-ts/lib/function";
+
+import { ServiceActivations as avroActivation } from "../../../generated/avro/dto/ServiceActivations";
+import { EnrichedLegacyActivationCosmosResource } from "../enriched-types/activation-pdv-enriched";
+
+export const buildAvroActivationObject = (
+  activationCosmosRecord: EnrichedLegacyActivationCosmosResource,
+): Omit<avroActivation, "schema" | "subject"> => ({
+  id:
+    activationCosmosRecord.userPDVId +
+    activationCosmosRecord.serviceId +
+    activationCosmosRecord._ts,
path: apps/io-services-cms-webapp/src/utils/ingestion/formatter/activation-avro-formatter.ts
user: login: rodoviti
body: question: Do we want to concatenate them with a separator?

Such as `<userPDVId>#<serviceId>#<timestamp>`
created_at: 2025-04-09T16:51:12Z
author_association: CONTRIBUTOR

PR comments:
user: login: changeset-bot[bot]
created_at: 2025-04-08T14:05:17Z
body: ###  🦋  Changeset detected

Latest commit: 3ca7f5e0497dc561acadc1ba03d0cb9c68948b98

**The changes in this PR will be included in the next version bump.**

<details><summary>This PR includes changesets to release 4 packages</summary>

  | Name                       | Type  |
| -------------------------- | ----- |
| @io-services-cms/models    | Patch |
| io-services-cms-webapp     | Patch |
| io-services-app-backend    | Patch |
| io-services-cms-backoffice | Patch |

</details>

Not sure what this means? [Click here  to learn what changesets are](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md).

[Click here if you're a maintainer who wants to add another changeset to this PR](https://github.com/pagopa/io-services-cms/new/IOPAE-1918-function-ingestion-activation?filename=.changeset/tricky-poems-collect.md&value=---%0A%22%40io-services-cms%2Fmodels%22%3A%20patch%0A%22io-services-cms-webapp%22%3A%20patch%0A---%0A%0A%5BIOPAE-1918%5D%20functions%20ingestion%20activation%0A)


author_association: NONE
user: login: github-actions[bot]
created_at: 2025-04-08T14:11:29Z
body: <h2>Coverage Report for App Backend (./apps/app-backend)</h2>
<table> <thead> <tr> <th align="center">Status</th> <th align="left">Category</th> <th align="right">Percentage</th> <th align="right">Covered / Total</th> </tr> </thead> <tbody> <tr> <td align="center">🔵</td> <td align="left">Lines</td> <td align="right">81.56%</td> <td align="right">951 / 1166</td> </tr> <tr> <td align="center">🔵</td> <td align="left">Statements</td> <td align="right">81.56%</td> <td align="right">951 / 1166</td> </tr> <tr> <td align="center">🔵</td> <td align="left">Functions</td> <td align="right">71.79%</td> <td align="right">28 / 39</td> </tr> <tr> <td align="center">🔵</td> <td align="left">Branches</td> <td align="right">93.84%</td> <td align="right">122 / 130</td> </tr> </tbody> </table><details><summary>File Coverage</summary>No changed files found.</details>
<em>Generated in workflow <a href=https://github.com/pagopa/io-services-cms/actions/runs/14376730348>#3423</a></em>

<!-- vitest-coverage-report-marker-App Backend -->
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-04-08T14:11:31Z
body: <h2>Coverage Report for Backoffice Frontend (./apps/backoffice)</h2>
<table> <thead> <tr> <th align="center">Status</th> <th align="left">Category</th> <th align="right">Percentage</th> <th align="right">Covered / Total</th> </tr> </thead> <tbody> <tr> <td align="center">🔵</td> <td align="left">Lines</td> <td align="right">22.84%</td> <td align="right">3048 / 13342</td> </tr> <tr> <td align="center">🔵</td> <td align="left">Statements</td> <td align="right">22.84%</td> <td align="right">3048 / 13342</td> </tr> <tr> <td align="center">🔵</td> <td align="left">Functions</td> <td align="right">28.3%</td> <td align="right">75 / 265</td> </tr> <tr> <td align="center">🔵</td> <td align="left">Branches</td> <td align="right">65.18%</td> <td align="right">176 / 270</td> </tr> </tbody> </table><details><summary>File Coverage</summary>No changed files found.</details>
<em>Generated in workflow <a href=https://github.com/pagopa/io-services-cms/actions/runs/14335622669>#3417</a></em>

<!-- vitest-coverage-report-marker-Backoffice Frontend -->
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-04-08T14:11:32Z
body: <h2>Coverage Report for Backoffice Backend (./apps/backoffice)</h2>
<table> <thead> <tr> <th align="center">Status</th> <th align="left">Category</th> <th align="right">Percentage</th> <th align="right">Covered / Total</th> </tr> </thead> <tbody> <tr> <td align="center">🔵</td> <td align="left">Lines</td> <td align="right">67.48%</td> <td align="right">4358 / 6458</td> </tr> <tr> <td align="center">🔵</td> <td align="left">Statements</td> <td align="right">67.48%</td> <td align="right">4358 / 6458</td> </tr> <tr> <td align="center">🔵</td> <td align="left">Functions</td> <td align="right">64.92%</td> <td align="right">137 / 211</td> </tr> <tr> <td align="center">🔵</td> <td align="left">Branches</td> <td align="right">82.86%</td> <td align="right">590 / 712</td> </tr> </tbody> </table><details><summary>File Coverage</summary>No changed files found.</details>
<em>Generated in workflow <a href=https://github.com/pagopa/io-services-cms/actions/runs/14335622669>#3417</a></em>

<!-- vitest-coverage-report-marker-Backoffice Backend -->
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-04-08T14:11:34Z
body: <h2>Coverage Report for Webapp (./apps/io-services-cms-webapp)</h2>
<table> <thead> <tr> <th align="center">Status</th> <th align="left">Category</th> <th align="right">Percentage</th> <th align="right">Covered / Total</th> </tr> </thead> <tbody> <tr> <td align="center">🔵</td> <td align="left">Lines</td> <td align="right">89.17%</td> <td align="right">8702 / 9758</td> </tr> <tr> <td align="center">🔵</td> <td align="left">Statements</td> <td align="right">89.17%</td> <td align="right">8702 / 9758</td> </tr> <tr> <td align="center">🔵</td> <td align="left">Functions</td> <td align="right">87.74%</td> <td align="right">272 / 310</td> </tr> <tr> <td align="center">🔵</td> <td align="left">Branches</td> <td align="right">90.96%</td> <td align="right">916 / 1007</td> </tr> </tbody> </table><details><summary>File Coverage</summary><table> <thead> <tr> <th align="left">File</th> <th align="right">Stmts</th> <th align="right">% Branch</th> <th align="right">% Funcs</th> <th align="right">% Lines</th> <th align="left">Uncovered Lines</th> </tr> </thead> <tbody> <tr> <td align="left" colspan="6"><b>Changed Files</b></td> </tr> <tr> <td align="left"><a href="https://github.com/pagopa/io-services-cms/blob/3ca7f5e0497dc561acadc1ba03d0cb9c68948b98/apps/io-services-cms-webapp/src/ingestion/request-activation-ingestion-retry-handler.ts">apps/io-services-cms-webapp/src/ingestion/request-activation-ingestion-retry-handler.ts</a></td> <td align="right">0%</td> <td align="right">0%</td> <td align="right">0%</td> <td align="right">0%</td> <td align="left"><a href="https://github.com/pagopa/io-services-cms/blob/3ca7f5e0497dc561acadc1ba03d0cb9c68948b98/apps/io-services-cms-webapp/src/ingestion/request-activation-ingestion-retry-handler.ts#L1-L48" class="text-red">1-48</a></td> </tr> <tr> <td align="left"><a href="https://github.com/pagopa/io-services-cms/blob/3ca7f5e0497dc561acadc1ba03d0cb9c68948b98/apps/io-services-cms-webapp/src/ingestion/service-topic-ingestor-handler.ts">apps/io-services-cms-webapp/src/ingestion/service-topic-ingestor-handler.ts</a></td> <td align="right">37.5%</td> <td align="right">100%</td> <td align="right">50%</td> <td align="right">37.5%</td> <td align="left"><a href="https://github.com/pagopa/io-services-cms/blob/3ca7f5e0497dc561acadc1ba03d0cb9c68948b98/apps/io-services-cms-webapp/src/ingestion/service-topic-ingestor-handler.ts#L18-L37" class="text-red">18-37</a>, <a href="https://github.com/pagopa/io-services-cms/blob/3ca7f5e0497dc561acadc1ba03d0cb9c68948b98/apps/io-services-cms-webapp/src/ingestion/service-topic-ingestor-handler.ts#L42-L56" class="text-red">42-56</a></td> </tr> <tr> <td align="left"><a href="https://github.com/pagopa/io-services-cms/blob/3ca7f5e0497dc561acadc1ba03d0cb9c68948b98/apps/io-services-cms-webapp/src/utils/fetch.ts">apps/io-services-cms-webapp/src/utils/fetch.ts</a></td> <td align="right">100%</td> <td align="right">100%</td> <td align="right">100%</td> <td align="right">100%</td> <td align="left"></td> </tr> <tr> <td align="left"><a href="https://github.com/pagopa/io-services-cms/blob/3ca7f5e0497dc561acadc1ba03d0cb9c68948b98/apps/io-services-cms-webapp/src/utils/pdvTokenizerClient.ts">apps/io-services-cms-webapp/src/utils/pdvTokenizerClient.ts</a></td> <td align="right">82.75%</td> <td align="right">100%</td> <td align="right">100%</td> <td align="right">82.75%</td> <td align="left"><a href="https://github.com/pagopa/io-services-cms/blob/3ca7f5e0497dc561acadc1ba03d0cb9c68948b98/apps/io-services-cms-webapp/src/utils/pdvTokenizerClient.ts#L22-L26" class="text-red">22-26</a></td> </tr> <tr> <td align="left"><a href="https://github.com/pagopa/io-services-cms/blob/3ca7f5e0497dc561acadc1ba03d0cb9c68948b98/apps/io-services-cms-webapp/src/utils/ingestion/ingestion-handlers.ts">apps/io-services-cms-webapp/src/utils/ingestion/ingestion-handlers.ts</a></td> <td align="right">100%</td> <td align="right">100%</td> <td align="right">100%</td> <td align="right">100%</td> <td align="left"></td> </tr> <tr> <td align="left"><a href="https://github.com/pagopa/io-services-cms/blob/3ca7f5e0497dc561acadc1ba03d0cb9c68948b98/apps/io-services-cms-webapp/src/utils/ingestion/enriched-types/activation-pdv-enriched.ts">apps/io-services-cms-webapp/src/utils/ingestion/enriched-types/activation-pdv-enriched.ts</a></td> <td align="right">0%</td> <td align="right">0%</td> <td align="right">0%</td> <td align="right">0%</td> <td align="left"><a href="https://github.com/pagopa/io-services-cms/blob/3ca7f5e0497dc561acadc1ba03d0cb9c68948b98/apps/io-services-cms-webapp/src/utils/ingestion/enriched-types/activation-pdv-enriched.ts#L1-L13" class="text-red">1-13</a></td> </tr> <tr> <td align="left"><a href="https://github.com/pagopa/io-services-cms/blob/3ca7f5e0497dc561acadc1ba03d0cb9c68948b98/apps/io-services-cms-webapp/src/utils/ingestion/enricher/pdv-enricher.ts">apps/io-services-cms-webapp/src/utils/ingestion/enricher/pdv-enricher.ts</a></td> <td align="right">34.48%</td> <td align="right">100%</td> <td align="right">100%</td> <td align="right">34.48%</td> <td align="left"><a href="https://github.com/pagopa/io-services-cms/blob/3ca7f5e0497dc561acadc1ba03d0cb9c68948b98/apps/io-services-cms-webapp/src/utils/ingestion/enricher/pdv-enricher.ts#L21-L58" class="text-red">21-58</a></td> </tr> <tr> <td align="left"><a href="https://github.com/pagopa/io-services-cms/blob/3ca7f5e0497dc561acadc1ba03d0cb9c68948b98/apps/io-services-cms-webapp/src/utils/ingestion/formatter/activation-avro-formatter.ts">apps/io-services-cms-webapp/src/utils/ingestion/formatter/activation-avro-formatter.ts</a></td> <td align="right">28.2%</td> <td align="right">100%</td> <td align="right">0%</td> <td align="right">28.2%</td> <td align="left"><a href="https://github.com/pagopa/io-services-cms/blob/3ca7f5e0497dc561acadc1ba03d0cb9c68948b98/apps/io-services-cms-webapp/src/utils/ingestion/formatter/activation-avro-formatter.ts#L10-L21" class="text-red">10-21</a>, <a href="https://github.com/pagopa/io-services-cms/blob/3ca7f5e0497dc561acadc1ba03d0cb9c68948b98/apps/io-services-cms-webapp/src/utils/ingestion/formatter/activation-avro-formatter.ts#L24-L39" class="text-red">24-39</a></td> </tr> <tr> <td align="left"><a href="https://github.com/pagopa/io-services-cms/blob/3ca7f5e0497dc561acadc1ba03d0cb9c68948b98/apps/io-services-cms-webapp/src/watchers/on-activation-ingestion-change.ts">apps/io-services-cms-webapp/src/watchers/on-activation-ingestion-change.ts</a></td> <td align="right">100%</td> <td align="right">100%</td> <td align="right">100%</td> <td align="right">100%</td> <td align="left"></td> </tr> </tbody> </table></details>
<em>Generated in workflow <a href=https://github.com/pagopa/io-services-cms/actions/runs/14376730348>#3423</a></em>

<!-- vitest-coverage-report-marker-Webapp -->
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-04-08T14:11:35Z
body: <h2>Coverage Report for External Clients (./packages/external-clients)</h2>
<table> <thead> <tr> <th align="center">Status</th> <th align="left">Category</th> <th align="right">Percentage</th> <th align="right">Covered / Total</th> </tr> </thead> <tbody> <tr> <td align="center">🔵</td> <td align="left">Lines</td> <td align="right">88.68%</td> <td align="right">1027 / 1158</td> </tr> <tr> <td align="center">🔵</td> <td align="left">Statements</td> <td align="right">88.68%</td> <td align="right">1027 / 1158</td> </tr> <tr> <td align="center">🔵</td> <td align="left">Functions</td> <td align="right">79.16%</td> <td align="right">38 / 48</td> </tr> <tr> <td align="center">🔵</td> <td align="left">Branches</td> <td align="right">95.14%</td> <td align="right">98 / 103</td> </tr> </tbody> </table><details><summary>File Coverage</summary>No changed files found.</details>
<em>Generated in workflow <a href=https://github.com/pagopa/io-services-cms/actions/runs/14376730348>#3423</a></em>

<!-- vitest-coverage-report-marker-External Clients -->
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-04-08T14:11:38Z
body: <h2>Coverage Report for Models (./packages/io-services-cms-models)</h2>
<table> <thead> <tr> <th align="center">Status</th> <th align="left">Category</th> <th align="right">Percentage</th> <th align="right">Covered / Total</th> </tr> </thead> <tbody> <tr> <td align="center">🔵</td> <td align="left">Lines</td> <td align="right">86.09%</td> <td align="right">2061 / 2394</td> </tr> <tr> <td align="center">🔵</td> <td align="left">Statements</td> <td align="right">86.09%</td> <td align="right">2061 / 2394</td> </tr> <tr> <td align="center">🔵</td> <td align="left">Functions</td> <td align="right">64.89%</td> <td align="right">61 / 94</td> </tr> <tr> <td align="center">🔵</td> <td align="left">Branches</td> <td align="right">96.68%</td> <td align="right">175 / 181</td> </tr> </tbody> </table><details><summary>File Coverage</summary><table> <thead> <tr> <th align="left">File</th> <th align="right">Stmts</th> <th align="right">% Branch</th> <th align="right">% Funcs</th> <th align="right">% Lines</th> <th align="left">Uncovered Lines</th> </tr> </thead> <tbody> <tr> <td align="left" colspan="6"><b>Changed Files</b></td> </tr> <tr> <td align="left"><a href="https://github.com/pagopa/io-services-cms/blob/3ca7f5e0497dc561acadc1ba03d0cb9c68948b98/packages/io-services-cms-models/src/index.ts">packages/io-services-cms-models/src/index.ts</a></td> <td align="right">100%</td> <td align="right">100%</td> <td align="right">100%</td> <td align="right">100%</td> <td align="left"></td> </tr> <tr> <td align="left"><a href="https://github.com/pagopa/io-services-cms/blob/3ca7f5e0497dc561acadc1ba03d0cb9c68948b98/packages/io-services-cms-models/src/activation-legacy/index.ts">packages/io-services-cms-models/src/activation-legacy/index.ts</a></td> <td align="right">100%</td> <td align="right">100%</td> <td align="right">100%</td> <td align="right">100%</td> <td align="left"></td> </tr> </tbody> </table></details>
<em>Generated in workflow <a href=https://github.com/pagopa/io-services-cms/actions/runs/14376730348>#3423</a></em>

<!-- vitest-coverage-report-marker-Models -->
author_association: CONTRIBUTOR
user: login: sonarqubecloud[bot]
created_at: 2025-04-10T09:09:46Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=pagopa_io-services-cms&pullRequest=1228) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=pagopa_io-services-cms&pullRequest=1228&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=pagopa_io-services-cms&pullRequest=1228&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=pagopa_io-services-cms&pullRequest=1228&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=pagopa_io-services-cms&pullRequest=1228&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=pagopa_io-services-cms&pullRequest=1228&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=pagopa_io-services-cms&pullRequest=1228)


author_association: NONE
user: login: github-actions[bot]
created_at: 2025-04-10T09:15:27Z
body: #### 📖 Terraform Plan ('infra/resources/prod') - success
<details>
<summary>Terraform Plan</summary>

```hcl

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # module.cms_function_app.module.cms_fn.azurerm_linux_function_app.this will be updated in-place
  ~ resource "azurerm_linux_function_app" "this" {
      ~ app_settings                                   = {
          + "AzureWebJobs.IngestionActivationWatcher.Disabled"                                                 = "1"
          + "AzureWebJobs.OnRequestActivationIngestionRetry.Disabled"                                          = "1"
          + "LEGACY_COSMOSDB_CONTAINER_ACTIVATIONS"                                                            = "activations"
          + "LEGACY_COSMOSDB_CONTAINER_ACTIVATIONS_LEASE"                                                      = "activations-ingestion-lease"
          + "PDV_TOKENIZER_API_KEY"                                                                            = "@Microsoft.KeyVault(VaultName=io-p-services-cms-kv;SecretName=PDV-TOKENIZER-API-KEY)"
          + "PDV_TOKENIZER_BASE_PATH"                                                                          = "/tokenizer/v1"
          + "PDV_TOKENIZER_BASE_URL"                                                                           = "https://api.tokenizer.pdv.pagopa.it"
            # (124 unchanged elements hidden)
        }
        id                                             = "/subscriptions/ec285037-c673-4f58-b594-d7c480da4e8b/resourceGroups/io-p-itn-svc-rg-01/providers/Microsoft.Web/sites/io-p-itn-svc-cms-func-01"
        name                                           = "io-p-itn-svc-cms-func-01"
        tags                                           = {
            "CostCenter"                                     = "TS310 - PAGAMENTI & SERVIZI"
            "CreatedBy"                                      = "Terraform"
            "Environment"                                    = "Prod"
            "ManagementTeam"                                 = "IO Enti & Servizi"
            "Owner"                                          = "IO"
            "Source"                                         = "https://github.com/pagopa/io-services-cms/infra/prod/italynorth"
        }
        # (31 unchanged attributes hidden)

      ~ sticky_settings {
          ~ app_setting_names       = [
              + "SLOT_TASK_HUBNAME",
              + "AzureFunctionsJobHost__extensions__durableTask__hubName",
                "APPINSIGHTS_SAMPLING_PERCENTAGE",
              - "AzureFunctionsJobHost__logging__applicationInsights__samplingSettings__initialSamplingPercentage",
              - "AzureFunctionsJobHost__logging__applicationInsights__samplingSettings__maxSamplingPercentage",
              + "AzureFunctionsWebHost__hostid",
                "AzureFunctionsJobHost__logging__applicationInsights__samplingSettings__minSamplingPercentage",
              - "AzureWebJobs.IngestionServiceHistoryWatcher.Disabled",
              - "AzureWebJobs.IngestionServiceLifecycleWatcher.Disabled",
              - "AzureWebJobs.IngestionServicePublicationWatcher.Disabled",
              + "AzureFunctionsJobHost__logging__applicationInsights__samplingSettings__maxSamplingPercentage",
              + "AzureFunctionsJobHost__logging__applicationInsights__samplingSettings__initialSamplingPercentage",
                "AzureWebJobs.LegacyServiceWatcher.Disabled",
              - "AzureWebJobs.OnRequestDeletion.Disabled",
              - "AzureWebJobs.OnRequestDetail.Disabled",
              + "AzureWebJobs.ServiceLifecycleWatcher.Disabled",
              + "AzureWebJobs.ServicePublicationWatcher.Disabled",
              + "AzureWebJobs.ServiceReviewChecker.Disabled",
              + "AzureWebJobs.ServiceHistoryWatcher.Disabled",
                "AzureWebJobs.OnRequestHistoricization.Disabled",
                # (1 unchanged element hidden)
                "AzureWebJobs.OnRequestReview.Disabled",
              - "AzureWebJobs.OnRequestReviewLegacy.Disabled",
              - "AzureWebJobs.OnRequestServicesHistoryIngestionRetry.Disabled",
              - "AzureWebJobs.OnRequestServicesLifecycleIngestionRetry.Disabled",
              - "AzureWebJobs.OnRequestServicesPublicationIngestionRetry.Disabled",
                "AzureWebJobs.OnRequestSyncCms.Disabled",
                "AzureWebJobs.OnRequestSyncLegacy.Disabled",
              + "AzureWebJobs.OnRequestReviewLegacy.Disabled",
              + "AzureWebJobs.ServiceReviewLegacyChecker.Disabled",
                "AzureWebJobs.OnRequestValidation.Disabled",
              - "AzureWebJobs.SelfcareGroupWatcher.Disabled",
              + "AzureWebJobs.OnRequestDeletion.Disabled",
              + "AzureWebJobs.OnRequestDetail.Disabled",
                "AzureWebJobs.ServiceDetailLifecycleWatcher.Disabled",
                "AzureWebJobs.ServiceDetailPublicationWatcher.Disabled",
              - "AzureWebJobs.ServiceHistoryWatcher.Disabled",
              - "AzureWebJobs.ServiceLifecycleWatcher.Disabled",
              - "AzureWebJobs.ServicePublicationWatcher.Disabled",
              - "AzureWebJobs.ServiceReviewChecker.Disabled",
              - "AzureWebJobs.ServiceReviewLegacyChecker.Disabled",
              + "AzureWebJobs.IngestionServicePublicationWatcher.Disabled",
              + "AzureWebJobs.OnRequestServicesPublicationIngestionRetry.Disabled",
              + "AzureWebJobs.IngestionServiceLifecycleWatcher.Disabled",
              + "AzureWebJobs.OnRequestServicesLifecycleIngestionRetry.Disabled",
              + "AzureWebJobs.IngestionServiceHistoryWatcher.Disabled",
              + "AzureWebJobs.OnRequestServicesHistoryIngestionRetry.Disabled",
                "AzureWebJobs.ServiceTopicsIngestor.Disabled",
              - "SLOT_TASK_HUBNAME",
              - "AzureFunctionsJobHost__extensions__durableTask__hubName",
              - "AzureFunctionsWebHost__hostid",
              + "AzureWebJobs.SelfcareGroupWatcher.Disabled",
              + "AzureWebJobs.IngestionActivationWatcher.Disabled",
              + "AzureWebJobs.OnRequestActivationIngestionRetry.Disabled",
            ]
            # (1 unchanged attribute hidden)
        }

        # (2 unchanged blocks hidden)
    }

  # module.cms_function_app.module.cms_fn.azurerm_linux_function_app_slot.this[0] will be updated in-place
  ~ resource "azurerm_linux_function_app_slot" "this" {
      ~ app_settings                                   = {
          + "AzureWebJobs.IngestionActivationWatcher.Disabled"                                                 = "1"
          + "AzureWebJobs.OnRequestActivationIngestionRetry.Disabled"                                          = "1"
          + "LEGACY_COSMOSDB_CONTAINER_ACTIVATIONS"                                                            = "activations"
          + "LEGACY_COSMOSDB_CONTAINER_ACTIVATIONS_LEASE"                                                      = "activations-ingestion-lease"
          + "PDV_TOKENIZER_API_KEY"                                                                            = "@Microsoft.KeyVault(VaultName=io-p-services-cms-kv;SecretName=PDV-TOKENIZER-API-KEY)"
          + "PDV_TOKENIZER_BASE_PATH"                                                                          = "/tokenizer/v1"
          + "PDV_TOKENIZER_BASE_URL"                                                                           = "https://api.tokenizer.pdv.pagopa.it"
            # (124 unchanged elements hidden)
        }
        id                                             = "/subscriptions/ec285037-c673-4f58-b594-d7c480da4e8b/resourceGroups/io-p-itn-svc-rg-01/providers/Microsoft.Web/sites/io-p-itn-svc-cms-func-01/slots/staging"
        name                                           = "staging"
        tags                                           = {
            "CostCenter"                                     = "TS310 - PAGAMENTI & SERVIZI"
            "CreatedBy"                                      = "Terraform"
            "Environment"                                    = "Prod"
            "ManagementTeam"                                 = "IO Enti & Servizi"
            "Owner"                                          = "IO"
            "Source"                                         = "https://github.com/pagopa/io-services-cms/infra/prod/italynorth"
        }
        # (29 unchanged attributes hidden)

        # (2 unchanged blocks hidden)
    }

Plan: 0 to add, 2 to change, 0 to destroy.

Warning: Argument is deprecated

  with module.ai_search.module.srch_snet.azurerm_subnet.this,
  on .terraform/modules/ai_search.srch_snet/subnet/main.tf line 23, in resource "azurerm_subnet" "this":
  23:   private_endpoint_network_policies_enabled     = var.private_endpoint_network_policies_enabled

`private_endpoint_network_policies_enabled` will be removed in favour of the
property `private_endpoint_network_policies` in version 4.0 of the AzureRM
Provider

(and 5 more similar warnings elsewhere)

─────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't
guarantee to take exactly these actions if you run "terraform apply" now.
```

</details>

author_association: CONTRIBUTOR