Skip to main content

High-level overview

Paper Channel follows a classic three-tier reactive architecture:
Inbound HTTP requests


┌───────────────────────────────────┐
│           REST Layer              │  Spring WebFlux controllers
│  (PaperMessagesRestV1Controller,  │
│   PaperChannelRestV1Controller,   │
│   …)                              │
└────────────────┬──────────────────┘

        reactive Mono / Flux


┌───────────────────────────────────┐
│          Service Layer            │  Business logic, prepare/send
│  (QueueListenerService,           │  orchestration, cost calculation
│   PaperSendService, …)            │
└──────┬─────────────────┬──────────┘
       │                 │
       ▼                 ▼
┌────────────┐   ┌───────────────────────────────┐
│  DynamoDB  │   │  External integrations        │
│  (tables   │   │  (MS clients + SQS producers) │
│   below)   │   └───────────────────────────────┘
└────────────┘
All layers use Project Reactor (Mono/Flux) for non-blocking I/O. SQS consumers (QueueListener) bridge the reactive pipeline from incoming queue messages.

REST controllers

Controllers live in src/main/java/it/pagopa/pn/paperchannel/rest/v1/.
ControllerResponsibility
PaperMessagesRestV1ControllerInternal API — handles prepare and send paper delivery requests
PaperChannelRestV1ControllerBack-office API — manages tenders, delivery drivers, FSU, costs, and geo keys
PaperCalculatorRestV2ControllerCost estimation endpoint for rate-card lookups
CheckAddressRestV1ControllerAddress validation and normalisation endpoint
PaperChannelPcRetryV1ControllerManual retry endpoint for stalled External Channel requests
NotificationReworkV1ControllerTimeline correction operations for re-processed notifications

DynamoDB entities

All DynamoDB entity classes live in src/main/java/it/pagopa/pn/paperchannel/middleware/db/entities/.
EntityPurpose
PnDeliveryRequestCore record for each prepare/send request lifecycle
PnEventMetaMetadata events associated with a delivery request
PnEventDematDematerialisation (scan) events for physical mail items
PnEventErrorUnrecoverable processing errors recorded for a request
PnRequestErrorErrors persisted when retry budgets are exhausted
PnTenderTender (gara d’appalto) contract header
PnDeliveryDriverDelivery driver (recapitista) linked to a tender
PnCostPostal rates for a given driver, product, and geo-zone combination
PnZoneGeographic zone definitions for postal routing
PnAddressEncrypted address record linked to a request
PnDiscoveredAddressAddress resolved from National Registries
PnAttachmentInfoAttachment metadata (safe-storage key, SHA256, page count)
PnAttachmentsConfigRules for which attachments are included per product/CAP
PnClientIDClient identifiers for cross-service calls
PnErrorMessageHuman-readable error messages for audit and alerting
PnErrorDetailsStructured error detail payloads
PnPaperChannelTenderSimplified tender records (new tender flow)
PnPaperChannelDeliveryDriverSimplified delivery driver records
PnPaperChannelCostSimplified cost records
PnPaperChannelGeoKeyGeographic routing keys for the simplified tender flow
PnDeliveryFileReferences to delivery documents stored in Safe Storage
PnRangeNumeric range definitions used in rule engines
PnRuleParamsParameters for the document-filter rule engine

External service clients

Generated WebClient stubs live under src/main/java/it/pagopa/pn/paperchannel/middleware/msclient/. Each interface is backed by an OpenAPI-generated reactive client in generated/openapi/msclient/.
Client interfaceRemote serviceKey operations
SafeStorageClientpn-safe-storageDownload and upload notification documents
NationalRegistryClientpn-national-registriesRequest verified address lookups
ExternalChannelClientpn-ec (External Channel)Submit postal send requests
AddressManagerClientpn-address-managerNormalise and validate Italian addresses
F24Clientpn-f24Request on-demand F24 PDF generation
RaddAltClientpn-radd-altInteract with RADD alternative access points
PaperTrackerClientpn-paper-trackerQuery physical mail tracking status

SQS queue topology

Consumed queues

Property keyPurpose
pn.paper-channel.queue-internalInternal retry and async-flow events (prepare, address-manager errors, EC errors, F24 errors)
pn.paper-channel.queue-national-registriesAddress lookup responses from National Registries
pn.paper-channel.queue-external-channelDelivery status updates from External Channel / carriers
pn.paper-channel.queue-f24F24 PDF-ready notifications
pn.paper-channel.queue-delayer-to-paperchannelPhase-2 prepare events relayed from the Delayer service

Produced queues / topics

Producer classDestinationPurpose
DeliveryPushMomProducerpn.paper-channel.queue-delivery-pushOutcome events sent to Delivery Push
NormalizeAddressQueueMomProducerpn.paper-channel.queue-normalize-addressAddress normalisation requests to Address Manager
PaperchannelToDelayerMomProducerpn.paper-channel.queue-paperchannel-to-delayerPhase-1 prepare results forwarded to the Delayer
InternalQueueMomProducerpn.paper-channel.queue-internalInternal retry scheduling
EventBridgeProducerEventBridge busPaperChannelOutcomeEvent published for cross-service consumers
OcrProducerpn.paper-channel.queue-url-ocr-inputsDocument images queued for OCR processing

Encryption flow

Sensitive address fields are encrypted before being persisted in DynamoDB using AWS envelope encryption:
  1. Paper Channel calls AWS KMS to generate a data key (configured via aws.kms.keyId).
  2. The AWS Encryption SDK (KmsEncryptionImpl) encrypts the address payload with the data key.
  3. Only the encrypted ciphertext is stored in DynamoDB (PnAddress, PnDiscoveredAddress).
  4. On read, the SDK retrieves and decrypts the data key from KMS and decrypts the payload in memory.
  5. A second encryption path (DataVaultEncryptionImpl) delegates to the Data Vault microservice for token-based pseudonymisation of PII.
For local development with LocalStack, you must obtain the KMS key ARN from the LocalStack startup logs and set it as aws.kms.keyId in your configuration. Without this, address encryption will fail at runtime.

Introduction

Return to the service overview and integration map.

Quickstart

Run the service locally and send your first prepare request.

Build docs developers (and LLMs) love