Skip to content

PEACH Integration

Quinn Hanson edited this page Sep 4, 2025 · 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

Record Parsing

Background & Goals

PCNS must display up-to-date permit lifecycle information drawn from PEACH Records. 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.

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 - GET peach/process/:recordId with optional system_id query param. Frontend will continue to call PCNS API for status/stage info.
  • No PEACH calls from the frontend.
  • New PCNS Endpoint POST peach/records - This will be called from a Cron job in OpenShift triggering the data fetching, parsing process, and updating of PCNS database.
  • New PEACH service and controller layer in PCNS' backend.
  • Parser - Converts raw (PIES) Record data from PEACH into status tracking data for a PCNS authorization.

Architecture

graph LR
    OpenShiftCronjob["CronJob"] -- POST peach/records --> Router["Peach Router"]
    Router --> Controller["Peach Controller"]
    Controller <--> PeachService["Peach Service"] 
    PeachService <-- HTTP GET /records --> PEACH["PEACH API"]
    Controller --> PermitService["Permit Service"]
    PermitService --> DB["PCNS DB"]
Loading

Flow description - The CronJob makes PCNS API call. The backend fetches from PEACH, parses, and updates PCNS DB Permit table.

Detailed API Design

Route Layer

Method Path Purpose
POST peach/records A trigger endpoint. Starts the backend process of calling PEACH and updating PCNS.
Responses
  • 202 - Ok, Accepted
  • 401 - Unauthorized.
  • 500 - Internal Server Error.

Controller Layer

syncPeachRecords(req, res)

  1. Invokes Peach Service Layer function getRecords().
  • If any PEACH error codes catch and throw as a PCNS Problem.
  1. Passes data to parser.
  2. Passes parser result to Permit Service Layer batchUpdatePermits(permitsToPatch)
Record Parser

Input: Raw Record payload from PEACH. Output: ParsedPermits: Permit[]

Rules/Steps:

  1. Sort Records by their process event(s) in process_event_set and/or on_hold_event_set by the event.start_datetime || event.start_date and/or event.end_datetime || event.end_date if applicable.
  2. TODO: More logic/sorting for isolating/setting most recent/accurate process event beyond dates will likely be needed. To add when implemented.
  3. “Current stage and status” is the "last/assigned" event in the sorted/transformed list.
  4. Build Permit object(s) to reflect the permits to be passed to PCNS DB.

Peach Service Layer

PeachService

Isolate PEACH api call(s).

getRecords() - Returns raw Record JSONs from PEACH API, using Axios.

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

Permit Service Layer

PermitService

Adding a service call to the current service/permit.ts.

patchPermits(permits) - Returns patched permits.

PermitController

Adding a trigger to upsertPermitController to fetch peach status data and call parser before updating new permit. Do not fail if nothing return from PEACH API, only return permit with no status updates.

patchPermits(permits) - Returns patched permits.

Data Model

No relational changes.

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 water and lands authorizations.
  • Nav side - Trigger one time PEACH update for adding new water/land authorizations on "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 hit POST endpoint described above.

ENV Variables:

  • PEACH_API_BASE_URL - e.g. https://<AZURE_PEACH_API_URL>/api/v1.
  • PEACH_CLIENT_ID / PEACH_CLIENT_SECRET - Injected by OpenShift secret. - TODO: Currently not needed as api endpoint is public, will implement when security is implemented on PEACH side.

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 process that updates PCNS DB
  3. Confirm final UI tracker/timeline design. Done

Clone this wiki locally