Skip to content

PEACH Integration

qhanson55 edited this page Mar 30, 2026 · 10 revisions

PCNS ↔ PEACH Integration Designs

This living document is the single home for all design work that connects the Permit Connect Navigator Service (PCNS) to the Permitting Exchange, Aggregation & Collection Hub (PEACH). Each integration feature is documented within the Design Modules section.


Table of Contents


Guiding Design Principles

  1. Authoritative Data - PEACH remains the single source of truth for permit information; PCNS only transforms for display.
  2. Server Side Transformation - All PEACH payloads are handled in the PCNS backend.
  3. Minimise Coupling - Future PEACH contract changes are isolated to a single service.
  4. Stateless Frontend - The UI never calls PEACH directly, preventing CORS, auth, and version issues.
  5. Extensibility - Each integration capability (e.g., Process Events, Record Linkage) lives in its own section under this hub document.
  6. Adhere to Existing Convetntions - Use existing PCNS API architectural conventions (Router → Controller → Services) and reuse the established axios pattern for third party API calls.

Design Modules

IMPORTANT: PCNS uses the Typscript types defined by PEACH in the backend peach layers and the PCNS file "re-defining" them will have to be updated when type/element changes are made to PEACH/PIES.

Record Parsing

Background & Goals

PCNS must display up-to-date permit lifecycle information drawn from PIES Records stored in PEACH. A Record groups authorization application events and process codes (e.g., Pre-Application, Referral, Decision) from a source system. One or more Records may be needed to be parsed to create complete tracking data for one authentication. (Note: Currently a record represents an entire authrorization of the associated record_id. This could be changed with upcoming Record Linkage changes.)

The goals of this design are:

  • Automate tracker updates so that staff are not manually reconciling data.
  • Parse the raw PIES payload into a minimal object that can be used to update PCNS DB.

Executive Level Changes

  • New PCNS Endpoint POST peach/record - This is a fetching endpoint coupled with a body (hence the post) that has permit tracking info to be used to call PEACH through PCNS' API and get up to date PEACH information for given tracking information.
  • No direct PEACH API calls from the frontend.
  • PEACH Sync entry point and Cron Job - A PCNS pod "copy" to allow a CRON scheduled job to execute a script for syncing of PEACH data to PCNS.
  • New PEACH route, controller, and service layer - Route to allow frontend to fetch PEACH data through PCNS, controller to facilitate new route and PEACH data syncing, service layer to connect to PEACH API.
  • Parser - Converts raw PIES Record data from PEACH into status tracking data for a PCNS authorization.

Architecture

graph LR
    OpenShiftCronjob["CronJob"] -- run peachSync.ts --> Entrypoint["Entrypoint \n peachSync.ts"]
    Entrypoint  --> Controller["Controller \n peach.ts"]
    Controller <--> PeachService["Service \n peach.ts"] 
    PeachService <-- HTTP GET peach/api/records --> PEACH["PEACH API"]
    Controller --> PermitService["Service \n permit.ts"]
    PermitService --> DB["PCNS DB"]
    Frontend <-- POST pcns/peach/record --> Router[Router \n peach.ts]
    Router <--> Controller
    Controller <--> Parser["Parser \n peach.ts"]
Loading

Flow description - The CronJob calls peachSync.ts entry point script triggering the backend to fetch needed data from PEACH API, parse, and update PCNS DB Permit and Permit Treacking tables.

Detailed API Design

Route Layer

Method Path Purpose
POST peach/record A fetching endpoint. Allows frontend to fetch PEACH status data for immediate status updates in the frontend.
Responses
  • 200 - Found and status data returned
  • 401 - Unauthorized.
  • 420 - Record not found.
  • 500 - Internal Server Error.

Controller Layer

findPriorityPermitTracking: Used to find the permit tracking with the highest priority to use for fetching most up to date PEACH data. (Note: this is in lieu of combining records to make one true sorce which was the original intention of PIES/PEACH. This may change with future versions of PEACH)

getPeachSummaryController: Calls PEACH API to get up to date status data and uses peachParser.ts to get a usable data format to return to frontend.

syncPeachRecords(req, res):

  1. Invokes Peach Service Layer function getRecords().
    • If any PEACH error codes catch and throw as a PCNS Problem.
  2. Passes data to parser.
  3. Iterates through parser results to check differential and call Permit Service Layer upsertPermit
Record Parser - peachParser.ts

Input: Raw PIES Records from PEACH API - PiesRecord[]. Output: parsedRecords: Record<string, PeachSummary> - Where the key is a concatination of the PiesRecord's record_id + system_id

PeachSummary - Is an interface that contains all needed status data parsed from the PIES Record

Rules/Steps:

Iterate through each given PIES Record and do the following:

  1. Sort the items in the Record's event sets (process_event_set and/or on_hold_event_set) by the event's start_datetime or event.start_date.
  2. Generate status data using the most recent process event or on hold event. The latest item is always used for status data, unless:
    • The most recent item is an on hold event and it has an end_datetime or end_date then the process event will be used.
    • The most recent item is an on hold event and the reason for the on hold is NOT missing information (MISSING_INFORMATION). (*Note: This may be temporary depending on if PCNS decides to handle more on hold reasons)
  3. Build PeachSummary object(s) to reflect the status of the permits to be passed to PCNS DB.

Note: More logic/sorting for isolating/setting most recent/accurate process event beyond dates may be needed in the future.

Peach Service Layer

PeachService

Isolate PEACH api call(s).

getRecord(recordId, sourceSystemId?) - Returns a raw Record JSON from PEACH, using Axios.

Data Model

No relational changes. Peach sync and parsing will intigrate into PCNS' data model so that non PEACH integrate permit types won't be affected.

Front-End Integration

  • Continue to get tracking data with same service calls - no change.
  • Prop side - Display Current Phase/Stage/Status in Tracker UI - no change.
  • Prop side - Render timeline/tracker (component already exists - new design coming) - no change.
  • Nav side - Grey out tracking fields for all PEACH integrated Permit types authorizations.
  • Nav side - Trigger one time PEACH update for adding new authorizations on "Automate & Publish" button click. If no data return display popup message.

Error Handling  &  Retry Strategy

All errors from PEACH will be converted to a PCNS Problem


Configuration & Deployment

CronJob

Will be deployed onto Openshift, simple CronJob to run peach sync script/entrypoint, described above.

ENV Variables/Secrets:

  • SERVER_PEACH_APIPATH - URL for PEACH API e.g. https://<AZURE_PEACH_API_URL>/api/v1.
  • SERVER_PEACH_TOKENURL - Token url for keycloak.
  • SERVER_PEACH_CLIENTID - Keycloak provide client id from PEACH.
  • SERVER_PEACH_CLIENTSECRET - Keycloak provide client secret from PEACH.

Risks & Mitigations

  • PEACH schema drift - Mitigated by single parsing service; update parser only.
  • Rate limiting - Implement simple change detection in controller.

Open Questions & Future Work

  1. Do we need to persist any data in PCNS DB? Yes, for now until PEACH evolves
  2. Should we utilize an in memory cache to hold commonly fetched PEACH data and expose a POST peach/process/:recordId/refresh or some kind of cronjob/scheduling for refreshing cache? CronJob to trigger script/entrypoint that updates PCNS DB
  3. Confirm final UI tracker/timeline design. Done

Adding Future Business Domains

Currently, the PCNS ↔ PEACH integration is explicitly scoped to the Water and Lands business domains. Extending this integration to support additional domains will require updates in both backend and frontend. Changes include, but are not limited to:

  • Tracking ID Prioritization: The findPriorityPermitTracking function dictates which permit tracking ID is used to fetch the most up to date PEACH data. Different business domains may need different prioritization logic. At a bare minimum, any new domain's tracking IDs must be appended to the PEACH_TRACKING_PRIORITY constant within the PEACH Controller to be utilizzed by the sync function.
  • Source System Kinds: The source_system_kind database table will have to set integrated field to true for all the corresponding row(s) for the new business domain tracking IDs.
  • Frontend Refactoring: The current UI implementation relies on specific components, props, local states, and constants tailored the current integrated business domains. Introducing a new domain requires evaluating and potentially refactoring these frontend elements to handle conditional rendering, new status types, and appropriate field-locking mechanisms.

Clone this wiki locally