Skip to main content

System Architecture

1. Overview

The Pinpoint Payment Gateway is a cloud-native, microservices-based payment processing platform built on GCP, integrating with TSYS TransIT via the Multipass API. The system follows a monorepo structure built with Bazel, deployed via Terraform, and automated through GitHub Actions CI/CD.

Rename note: the current gateway data model is Organization -> Location. This architecture page still contains some legacy merchant naming in endpoint examples, claims, and older service descriptions where the shipped wire/API alias remains /merchants or merchantId; in those cases, treat the value as the concrete location record.


2. High-Level Architecture

The gateway is deployed across two GCP projects for PCI-DSS compliance. The CDE (Cardholder Data Environment) project contains all services that handle TransIT credentials or cardholder data. External clients (PeakPOS, e-commerce backends, future integrators) authenticate via OAuth and never access the CDE directly.

┌─────────────────────────────────────────────────────────────────────────────┐
│ CLIENTS (each in their own GCP project, OUT of CDE) │
│ │
│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────────────┐ │
│ │ PeakPOS │ │ E-commerce │ │ Future Clients │ │
│ │ Management API │ │ Backends │ │ (other POS, SaaS) │ │
│ │ │ │ │ │ │ │
│ │ Scopes: │ │ Scopes: │ │ Scopes: │ │
│ │ merchant:activate│ │ txn:process │ │ (per agreement) │ │
│ │ provision:request│ │ session:create │ │ │ │
│ └──────┬───────────┘ └──────┬───────────┘ └───────────┬──────────────┘ │
└─────────┼──────────────────────┼───────────────────────────┼────────────────┘
│ │ │
│ OAuth tokens (scoped per client) │
│ │ │
┌─────────┼──────────────────────┼───────────────────────────┼────────────────┐
│ │ Cloud Armor / LB (WAF + DDoS + TLS) │ │
│ │ API Gateway (Cloud Endpoints) │ │
│ ▼ ▼ ▼ │
│ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ FRONTENDS │ │
│ │ │ │
│ │ ┌─────────────────────┐ ┌─────────────────────┐ │ │
│ │ │ Management Portal │ │ Online Payment │ │ │
│ │ │ (React 19 / Vite 7) │ │ Website │ │ │
│ │ │ Firebase Auth login │ │ Hosted checkout UI │ │ │
│ │ └─────────┬───────────┘ └──────────┬──────────┘ │ │
│ │ │ │ │ │
│ └────────────┼────────────────────────────────┼───────────────────────┘ │
│ │ │ │
│ │ REST/JSON │ REST/JSON │
│ ▼ ▼ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ BACKEND SERVICES (all Cloud Run) │ │
│ │ │ │
│ │ ┌──────────────┐ ┌──────────────┐ │ │
│ │ │ Auth Service │ │ Status │ │ │
│ │ │ :8081 │ │ Service :8086│ │ │
│ │ │ OAuth2 issuer│ │ Health agg. │ │ │
│ │ │ JWK endpoint │ │ │ │ │
│ │ └──────┬───────┘ └──────────────┘ │ │
│ │ │ JWK (/.well-known/jwks.json) │ │
│ │ │ fetched by ALL services for token validation │ │
│ │ ▼ │ │
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────────┐ │ │
│ │ │ Management │ │ Online Txn │ │ Merchant Onboarding │ │ │
│ │ │ Service │ │ Service │ │ Service │ │ │
│ │ │ :8083 │ │ :8084 │ │ :8085 │ │ │
│ │ └──────┬───────┘ └──────┬───────┘ └──┬───────────┬───────────┘ │ │
│ │ │ │ │ │ │ │
│ │ │ proxy/delegate │ delegate │ │ │ │
│ │ └────────┐ ┌─────┘ │ │ │ │
│ │ ▼ ▼ │ │ │ │
│ │ ┌──────────────┐ │ │ │ │
│ │ │ Processing │◄──────────────┘ │ │ │
│ │ │ Service │ internal creds API │ │ │
│ │ │ :8082 │ │ │ │
│ │ └──────┬───────┘ │ │ │
│ │ │ │ │ │
│ └──────────────────┼───────────────────────────────────┼───────────────┘ │
│ │ │ │
│ ┌──────────────────┼───────────────────────────────────┼───────────────┐ │
│ │ CDE INFRASTRUCTURE (peakpos-cde, PCI scoped) │ │ │
│ │ │ │ │ │
│ │ ┌────────────┐ │ ┌───────────┐ ┌────────────┐ │ │ │
│ │ │ Spanner │◄─┘ │ Pub/Sub │ │ Cloud │ │ │ │
│ │ │ (CDE DB) │ │ (Events) │ │ Scheduler │ │ │ │
│ │ └────────────┘ └───────────┘ └────────────┘ │ │ │
│ │ │ │ │
│ │ ┌────────────┐ ┌────────────┐ ┌───────────┐ │ │ │
│ │ │ Secret │ │ Cloud KMS │ │ Cloud │ │ │ │
│ │ │ Manager │ │ (cred enc) │ │ Storage │ │ │ │
│ │ └────────────┘ └────────────┘ └───────────┘ │ │ │
│ └──────────────────────────────────────────────────────┼───────────────┘ │
│ │ │
│ GCP Project: peakpos-cde (PCI SCOPED) │ │
└─────────────────────────────────────────────────────────┼────────────────────┘

┌────────────────┼────────────────┐
▼ ▼ │
┌──────────────────┐ ┌──────────────┐ │
│ TSYS TransIT │ │ NexGO XTMS │ │
│ Multipass API │ │ (device TMS) │ │
└──────────────────┘ └──────┬───────┘ │
│ │
▼ │
┌──────────────┐ │
│ NexGO Device │ │
│ SmartConnect │ │
│ (holds creds │ │
│ internally) │ │
└──────┬───────┘ │
│ │
┌────────┘ │
▼ │
┌──────────────────┐ │
│ Kotlin SDK │ │
│ (on device/server)│──────────────┘
└──────────────────┘
calls Auth, Online Txn,
Processing services

Why Two GCP Projects?

ConcernsSingle projectTwo projects (chosen)
DecisionOption consideredChosen architecture - separate project for CDE (PCI scoped)
PCI audit scopeEntire project in scopeOnly CDE project in scope
IAM isolationShared IAM policiesHard boundary - separate IAM
Blast radiusCompromise affects everythingCDE isolated from client infra
CostShared resources~$65/mo extra for CDE Spanner
ComplexitySimplerCross-project IAM + HTTPS (trivial with Cloud Run)

3. Technology Stack

LayerTechnologyJustification
LanguageKotlin (services), TypeScript (frontends)Kotlin for all backend services; TS for modern web UIs
FrameworkSpring Boot 4.0.2Industry standard for payment processing, excellent observability
BuildBazelMonorepo support, hermetic builds, caching
DatabaseCloud Spanner (PostgreSQL dialect)ACID compliance, horizontal scaling, matches PeakPOS monorepo
MessagingCloud Pub/SubAsync event processing, webhook delivery
Auth (Portal)Firebase Auth + SAML SSOManaged auth with enterprise SSO support
Auth (API)OAuth2 + JWT (Spring Authorization Server)Standard API authentication via Auth Service
SecretsGCP Secret ManagerAPI keys, TransIT credentials, signing keys
ComputeCloud RunAuto-scaling, pay-per-use, no cluster management
IaCTerraformDeclarative infrastructure, state management
CI/CDGitHub ActionsNative GitHub integration, monorepo support
ContainerDocker (Ubuntu / Debian)Branded as "Peak Gateway"
MonitoringCloud Monitoring + Cloud LoggingNative GCP observability stack
CDN/WAFCloud Armor + Cloud Load BalancingDDoS protection, TLS termination

4. Monorepo Structure

gateway/
├── MODULE.bazel
├── BUILD.bazel
├── .bazelrc
├── docker-compose.dev.yml
├── .github/
│ └── workflows/
│ ├── ci.yml
│ ├── deploy-staging.yml
│ └── deploy-production.yml
├── docs/specs/ # Legacy spec sources (mirrored into support-docs)
├── websites/support-docs/docs/ # Support docs (Docusaurus)
├── infra/
│ └── terraform/
│ ├── main.tf
│ ├── variables.tf
│ ├── outputs.tf
│ ├── environments/
│ │ ├── staging/
│ │ └── production/
│ └── modules/
│ ├── cloud-run/
│ ├── spanner/
│ ├── iam/
│ ├── networking/
│ ├── pubsub/
│ ├── secrets/
│ ├── firebase/
│ ├── load-balancer/
│ ├── artifact-registry/
│ ├── monitoring/
│ ├── project/
│ ├── kms/
│ ├── security/
│ ├── storage/
│ ├── identity-platform/
│ └── apphub/
├── services/
│ ├── processing/ # Processing Microservice
│ │ ├── BUILD.bazel
│ │ ├── src/main/kotlin/
│ │ └── src/test/kotlin/
│ ├── management/ # Management Microservice
│ │ ├── BUILD.bazel
│ │ ├── src/main/kotlin/
│ │ └── src/test/kotlin/
│ ├── online-txn/ # Online Transaction Microservice
│ │ ├── BUILD.bazel
│ │ ├── src/main/kotlin/
│ │ └── src/test/kotlin/
│ ├── merchant-onboarding/ # Merchant Onboarding Microservice
│ │ ├── BUILD.bazel
│ │ ├── src/main/kotlin/
│ │ └── src/test/kotlin/
│ ├── auth/ # Gateway Auth Service
│ │ ├── BUILD.bazel
│ │ ├── src/main/kotlin/
│ │ └── src/test/kotlin/
│ └── status/ # Status Microservice
│ ├── BUILD.bazel
│ ├── src/main/kotlin/
│ └── src/test/kotlin/
├── portal/ # Management Portal (web)
│ ├── BUILD.bazel
│ ├── package.json
│ └── src/
├── website/ # Online Payment Website
│ ├── BUILD.bazel
│ ├── package.json
│ └── src/
├── sdks/
│ └── kotlin/
│ ├── gateway-sdk-core/ # KMP - JVM, Android, iOS (future)
│ │ ├── BUILD.bazel
│ │ └── src/
│ └── gateway-sdk-android/ # Android-only - ViewModel, lifecycle
│ ├── BUILD.bazel
│ └── src/
├── libs/ # Shared libraries
│ ├── common/ # Common utilities
│ │ ├── BUILD.bazel
│ │ └── src/
│ ├── transit-client/ # TransIT Multipass API client (internal)
│ │ ├── BUILD.bazel
│ │ └── src/
│ ├── xtms-client/ # XTMS Cloud Open API client (internal)
│ │ ├── BUILD.bazel
│ │ └── src/
│ ├── schema/ # SQLDelight schema & types
│ │ ├── BUILD.bazel
│ │ └── src/
│ └── security/ # Common security & auth filters
│ ├── BUILD.bazel
│ └── src/
├── scripts/ # Local dev helpers
│ ├── dev.sh
│ └── dev.env
└── tools/
├── lint/
│ └── ktlint.sh
└── scripts/

5. Service Communication

5.1 Per-Service Communication Map

Each service's exact inbound and outbound connections, derived from source code and configuration.

Auth Service (:8081)

Spring Authorization Server. Issues OAuth2 tokens and publishes JWK keys for token validation by all other services.

DirectionTargetProtocolPurpose
OutboundCloud SpannerJDBC (PGAdapter)OAuth client registrations, token metadata
OutboundFirebase AuthAdmin SDKPortal user identity verification
InboundAll servicesHTTPS GETJWK endpoint (/auth/.well-known/jwks.json) on the public gateway or direct auth service URL for token validation
InboundAll clientsHTTPS POSTOAuth2 token issuance (/auth/oauth2/token) on the public gateway
InboundPortalHTTPSOAuth client admin APIs

Processing Service (:8082)

Core payment engine. All payment operations flow through this service.

DirectionTargetProtocolPurpose
OutboundTSYS TransIT Multipass APIHTTPSSale, Auth, Capture, Void, Refund, Batch, Tip Adjust, L2/L3 Enrich (via transit-client lib)
OutboundMerchant Onboarding ServiceHTTPS (VPC-internal)Fetch merchant TransIT credentials for transaction routing. Authoritative source is the credential_profiles lookup keyed off the merchant's assigned profile; the legacy GET /internal/merchants/{id}/credentials route (backed by merchant_credentials) is still wired on the server but is deprecated and slated for retirement alongside the CredentialService rewrite (ORG-14 A1b).
OutboundCloud SpannerJDBC (PGAdapter)transactions, settlement_batches, subscriptions, subscription_billing_events, batch_settlement_config
OutboundCloud Pub/SubPublishTopics: transaction-events, subscription-events
OutboundAuth ServiceHTTPS GETFetch JWK for inbound token validation
InboundManagement ServiceHTTPSProxied transaction queries, void, refund, settlement, subscription reports
InboundOnline Txn ServiceHTTPSDelegated payment processing (sale, auth, token charge)
InboundCloud SchedulerPub/SubHourly trigger for recurring billing engine
InboundKotlin SDKHTTPSDirect transaction processing (card-present via SmartConnect)

Management Service (:8083)

Backend for the Management Portal. Proxies transaction and subscription operations to the Processing Service.

DirectionTargetProtocolPurpose
OutboundProcessing ServiceHTTPSProxy: transaction search, void, refund, settlement queries, subscription management, reports
OutboundCloud SpannerJDBC (PGAdapter)merchants, portal_users, user_merchant_access, audit_log
OutboundFirebase AuthAdmin SDKUser creation, custom claims (RBAC), SAML provider CRUD
OutboundAuth ServiceHTTPS GETFetch JWK for inbound token validation
InboundManagement PortalHTTPSAll portal API calls (merchants, users, reports, SAML config)

Online Txn Service (:8084)

E-commerce payment flows. Manages checkout sessions, hosted payments, webhooks, and API keys. Delegates actual payment processing to the Processing Service.

DirectionTargetProtocolPurpose
OutboundProcessing ServiceHTTPSDelegate: sale, auth, token charge for checkout sessions and card-on-file payments
OutboundCloud SpannerJDBC (PGAdapter)checkout_sessions, stored_tokens, api_keys, webhook_deliveries, subscription_webhook_config
OutboundCloud Pub/SubSubscribe + PublishSubscribe: transaction-events (for webhook triggers). Publish: webhook-delivery
OutboundMerchant webhook URLsHTTPS POSTWebhook delivery with HMAC-SHA256 signature
OutboundAuth ServiceHTTPS GETFetch JWK for inbound token validation
InboundOnline Payment WebsiteHTTPSCheckout session UI, payment form submissions
InboundE-commerce backendsHTTPSCheckout session creation, token payments, subscription creation, API key management
InboundKotlin SDKHTTPSServer-to-server payments, token management

Merchant Onboarding Service (:8085)

Bridges TransIT credentials to physical payment devices. Runs entirely within the CDE project. The only service that communicates with NexGO XTMS.

DirectionTargetProtocolPurpose
OutboundTSYS TransIT MerchantActivation APIHTTPSGenerate deviceID + transactionKey (via transit-client lib)
OutboundNexGO XTMS Cloud Open APIHTTPSCreate merchant, bind device, push credentials (via xtms-client lib)
OutboundCloud SpannerJDBC (PGAdapter)provisioning_jobs, credential_profiles (authoritative), merchant_credentials (legacy, retained server-side until ORG-14 A1b), provisioning_audit_log
OutboundCloud KMSgRPCEncrypt/decrypt TransIT credentials (AES-256-GCM) before Spanner storage
OutboundSecret ManagergRPCRead TransIT developer credentials (developerID, developerKey)
OutboundCloud Pub/SubPublishTopic: provisioning-events
OutboundAuth ServiceHTTPS GETFetch JWK for inbound token validation
InboundProcessing ServiceHTTPS (VPC-internal)Returns decrypted TransIT credentials for transaction routing. New callers read from the credential_profiles-backed surface; the legacy GET /internal/merchants/{id}/credentials route remains wired server-side for backwards compatibility and is tracked for removal in ORG-14 A1b.
InboundPeakPOS Management APIHTTPS (cross-project)POST /api/v1/provisioning/jobs - trigger provisioning workflow
InboundManagement Portal (via gateway)HTTPSProvisioning job status, audit logs

Status Service (:8086)

Lightweight health aggregation. No database, no Pub/Sub, no external API calls.

DirectionTargetProtocolPurpose
OutboundAll other servicesHTTPS GET/actuator/health - aggregate health status
InboundCloud MonitoringHTTPS GETUptime checks
InboundAny clientHTTPS GETAggregated gateway health

5.2 Service-to-Service Call Graph

Summary of which services call which. Every arrow represents a synchronous HTTPS call.

┌───────────────────────────────────────────┐
│ Auth Service │
│ JWK keys fetched by ALL services below │
└──────────────────┬────────────────────────┘
│ JWK
┌───────────────┬───────────────┼───────────────┬─────────────────┐
▼ ▼ ▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌───────────┐
│ Management │ │ Online Txn │ │ Processing │ │ Device Prov │ │ Status │
│ Service │ │ Service │ │ Service │ │ Service │ │ Service │
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘ └──────────────┘ └───────────┘
│ │ ▲ │ ▲
│ proxy txn, │ delegate │ │ GET /internal │
│ settlements, │ payments │ │ /credentials │
│ subscriptions │ │ │ │
└────────────────┴───────────────┘ └────────────────┘
both call Processing Processing calls
Merchant Onboarding

5.3 Frontend-to-Backend Mapping

FrontendBackend ServiceAuth MethodWhat it does
Management Portal (React)Management Service (:8083)Firebase Auth ID tokenMerchant CRUD, user mgmt, SAML config, reports, audit log
Online Payment WebsiteOnline Txn Service (:8084)Session-based (checkout session ID)Checkout flow, payment form submission
Kotlin SDK (server)Auth Service (:8081)OAuth2 client credentialsObtain scoped access token
Kotlin SDK (server)Online Txn Service (:8084)OAuth2 bearer token / API keyCheckout sessions, token payments, subscriptions
Kotlin SDK (server)Processing Service (:8082)OAuth2 bearer tokenDirect transaction processing (card-present)

5.4 External Client-to-Service Mapping

External ClientServices CalledOAuth ScopesPurpose
PeakPOS Management APIAuth → Merchant Onboardingmerchant:activate, provision:requestMerchant onboarding, merchant onboarding
PeakPOS Terminal APIAuth → Processingtxn:process, batch:manageCard-present transactions via SmartConnect
E-commerce backendsAuth → Online Txntxn:process, session:createCard-not-present transactions, hosted checkout
Gateway PortalAuth → Managementadmin:*Full gateway administration

5.5 External System Integrations

External SystemCalled ByLibraryProtocolPurpose
TSYS TransIT Multipass APIProcessing Servicelibs/transit-clientHTTPS (JWT + signature)Transaction processing: Sale, Auth, Capture, Void, Refund, Batch, L2/L3
TSYS TransIT MerchantActivationMerchant Onboarding Servicelibs/transit-clientHTTPS (JWT + signature)Generate deviceID + transactionKey for new merchants
NexGO XTMS Cloud Open APIMerchant Onboarding Servicelibs/xtms-clientHTTPS (SHA-256 signature)Device management, credential push, parameter configuration
Firebase Auth / Identity PlatformAuth Service, Management ServiceFirebase Admin SDKgRPCUser identity, SAML SSO providers, custom claims
Merchant webhook URLsOnline Txn Service(direct)HTTPS POSTWebhook delivery for payment and subscription events

5.6 Shared Library Usage

LibraryPurposeUsed By
libs/transit-clientTSYS TransIT Multipass API client (HTTP client, JWT auth, request signing)Processing, Merchant Onboarding
libs/xtms-clientNexGO XTMS Cloud Open API client (HTTP client, SHA-256 signature auth)Merchant Onboarding
libs/securityOAuth/JWT validation filters, @RequireScope and @RequireRole annotations, JWK integrationAll services (except Status)
libs/schemaSQLDelight-generated Spanner schema and Kotlin typesAll services with database access
libs/commonShared utilities, error models, ApiResponse DTOsAll services

5.7 Pub/Sub Topics and Subscribers

TopicPublisherSubscribersEvents
transaction-eventsProcessing ServiceOnline Txn Service (webhook delivery), Management Portal (real-time updates)transaction.approved, transaction.declined, transaction.voided, transaction.refunded, transaction.settled
subscription-eventsProcessing ServiceOnline Txn Service (webhook delivery)subscription.created, subscription.billed, subscription.payment_failed, subscription.past_due, subscription.cancelled, subscription.paused, subscription.resumed
provisioning-eventsMerchant Onboarding ServiceManagement Portal (status updates), callback delivery, alerting (PagerDuty)PROVISION_COMPLETED, PROVISION_FAILED, XTMS_PUSH_FAILED
webhook-deliveryOnline Txn ServiceOnline Txn Service (retry worker)webhook.send - queued webhook delivery attempts

5.8 Cloud Scheduler Jobs

ScheduleTargetPurpose
HourlyProcessing Service (via Pub/Sub)Recurring billing engine: query subscriptions where next_billing_date <= NOW(), execute TOKEN sales

6. Data Architecture

Cloud Spanner (CDE Project - PostgreSQL dialect)

Dedicated Spanner instance in the CDE project. Keeps the PeakPOS monorepo's existing Spanner instance out of PCI scope.

Table groupOwner ServicePurpose
merchants, merchant_configsManagementMerchant profiles, configurations, boarding data
portal_users, user_merchant_accessManagementPortal users, roles, permissions
audit_logManagementAdministrative action audit trail
transactions, settlement_batches, batch_settlement_configProcessingTransaction records, settlement batches, scheduling config
subscriptions, subscription_billing_eventsProcessingRecurring billing lifecycle
checkout_sessions, stored_tokensOnline TxnCheckout sessions, tokenized payment data
api_keysOnline TxnMerchant API keys for SDK/API access
webhook_deliveries, subscription_webhook_configOnline TxnWebhook delivery tracking and merchant webhook config
credential_profilesMerchant OnboardingKMS-encrypted TransIT credentials scoped to an organization and assignable to merchants/locations (authoritative source). See libs/schema/.../CredentialProfile.sq.
merchant_credentialsMerchant OnboardingLegacy per-merchant KMS-encrypted TransIT credentials (BYTEA). Retained server-side for backwards compatibility; being migrated onto credential_profiles in ORG-14 A1b.
provisioning_jobs, provisioning_audit_logMerchant OnboardingProvisioning workflow state and audit trail

Key Design Decisions

  • Separate Spanner instance in CDE project (~$65/mo) - keeps PeakPOS Spanner out of PCI audit scope
  • PostgreSQL dialect - consistent with PeakPOS monorepo conventions
  • Read replicas for reporting queries - Avoids impacting transaction processing
  • Encryption at rest - Customer-managed encryption keys (CMEK) via Cloud KMS
  • Point-in-time recovery - Enabled, 7-day retention minimum
  • No PAN storage - We never store raw card numbers; all card data is tokenized by TransIT
  • Credential encryption - TransIT credentials (deviceID, transactionKey) encrypted via Cloud KMS before storage, stored as BYTEA

7. Security Architecture

Network Security

  • All services run in a VPC with private IP
  • Cloud Run services communicate over VPC connector (serverless VPC access)
  • No public IP on database
  • Cloud Armor WAF rules: OWASP top 10, geo-blocking, rate limiting

Authentication & Authorization

BoundaryMethod
Gateway Portal usersFirebase Auth (email/password + SAML SSO) on CDE project
External clients (PeakPOS, e-commerce)OAuth2 tokens issued by Gateway Auth Service (scoped)
API clients (Kotlin SDK)API key + OAuth token
Service-to-service (within CDE)GCP IAM + service account identity
Cross-project (peakpos → peakpos-cde)Cloud Run IAM (roles/run.invoker) + OAuth token
TransIT APITransIT deviceID + transactionKey (JWT + signature)
NexGO XTMSSHA-256 signature with appId + key (per-request nonce + timestamp)

Multi-Tenant Client Model

The gateway serves multiple clients. Each client gets:

  • An OAuth client registration with specific scopes
  • A client_id for audit trail attribution
  • Rate limits per client
  • Isolated merchant data (clients cannot see each other's merchants)
ClientScopesPurpose
PeakPOS Management APImerchant:activate, provision:requestMerchant onboarding, merchant onboarding
PeakPOS Terminal APItxn:process, batch:manageCard-present transactions via SmartConnect
E-commerce backendtxn:process, session:createCard-not-present transactions
Gateway Portaladmin:*Full gateway administration

mTLS - Not Used (Intentional)

The gateway does not use mTLS. All authentication is handled by OAuth2 tokens and Cloud Run IAM, which fully cover every current communication path. mTLS would add certificate authority management, cert issuance/rotation, and onboarding infrastructure for zero additional security benefit over what Cloud Run IAM already provides (mutual service identity verification).

Future consideration: When the gateway supports direct device-to-gateway card-present transactions (devices calling the gateway to process payments, bypassing SmartConnect), mTLS should be revisited. Physical payment terminals on PCI-compliant firmware cannot use Play Integrity or similar Google-dependent attestation - mTLS with hardware-backed client certificates is the established industry pattern for payment terminal authentication (as used in the PeakPOS monorepo's terminal-api today).

PCI-DSS Compliance

  • Two GCP projects: peakpos (out of CDE) and peakpos-cde (PCI scoped)
  • SAQ-D scope for CDE server-side components
  • No raw PAN touches our infrastructure (semi-integrated + tokenization)
  • All secrets in Secret Manager (not env vars, not config files)
  • TransIT credentials encrypted via Cloud KMS before Spanner storage
  • Audit logging on all transaction and provisioning operations
  • Network segmentation via VPC + project boundary
  • External clients never receive raw TransIT credentials

Secret Management

All sensitive values stored in GCP Secret Manager (CDE project):

  • TransIT developer credentials (developerID, developerKey)
  • Per-merchant credentials encrypted via Cloud KMS in Spanner (not Secret Manager)
  • Database connection strings
  • Firebase service account keys
  • OAuth signing keys
  • API keys for SDK authentication

8. Observability

ConcernToolDetails
LogsCloud LoggingStructured JSON logging, 30-day retention
MetricsCloud MonitoringCustom dashboards, SLO tracking
TracesCloud TraceDistributed tracing across services
AlertsCloud Monitoring AlertingPagerDuty integration for P0/P1
UptimeCloud Monitoring Uptime ChecksExternal health checks every 60s

Key Metrics

  • Transaction success rate (target: 99.9%)
  • Transaction latency p50/p95/p99
  • TransIT API latency and error rate
  • Settlement batch success rate
  • Portal/website availability

9. Disaster Recovery

ComponentRPORTOStrategy
SpannerNear-zero< 5 minMulti-zone by default, point-in-time recovery enabled
Cloud RunN/A< 5 minAuto-scaling, multi-zone
SecretsN/AN/AManaged by GCP, globally replicated

10. PeakPOS Monorepo Integration

The PeakPOS monorepo (peaksystems/monorepo) has existing transaction, batch, and payment configuration infrastructure. The gateway integrates with - not replaces - this existing infrastructure.

Existing Infrastructure

ComponentLocationPurpose
TransactionServiceterminal-apiCreates transactions with processor_reference_id, external_auth_code, external_auth_provider
BatchServiceterminal-apiBatch lifecycle: open → close → settle with settlement response tracking
CardAuthorization schemaspecifications/schemaStores processor responses: auth code, card type, EMV data (AID, TVR, TSI), amounts
PaymentConfigServicemerchant-apiPer-terminal processor configuration management
MkonnektServicemerchant-apiExternal API integration pattern with circuit breaker (reference implementation)
PaymentInterfaceConfigDtolibs/securityShared payment interface config model (apiKey, appIdentifier, environment)

Integration Points

  1. Processor Type Extension: card_authorizations.processor_type field currently defaults to "nmi" - add "tsys" / "transit" as a new option
  2. Payment Config Storage: Store TSYS credentials (merchant ID, TID, API keys) in existing terminal_payment_configs.interfaces JSONB field
  3. Card Authorization Mapping: Map TransIT/MultiPass responses to existing card_authorizations schema fields
  4. Batch Settlement Routing: Extend BatchService.settleBatch() to route to TransIT when processor is TSYS
  5. Raw Response Storage: TSYS-specific response data in card_authorizations.raw_response JSONB - no schema migration needed
  6. EMV Data Fields: Existing emv_aid, emv_tvr, emv_tsi fields map directly to NexGO terminal EMV output

Key Existing Fields

FieldTablePurpose
processor_reference_idtransactionsGateway transaction ID
external_auth_codetransactionsAuthorization code from processor
external_auth_providertransactionsProcessor name (e.g., "nmi", "tsys")
processor_typecard_authorizationsDefaults to "nmi", extensible for TSYS
raw_responsecard_authorizationsJSONB for full processor response
tip_amountcard_authorizationsTip (adjustable post-auth)
fee_amountcard_authorizationsProcessing fee
emv_aid, emv_tvr, emv_tsicard_authorizationsEMV data fields