Management Service
Overview
gateway-management is the portal backend and the public BFF for internal
Gateway capabilities. It owns organizations, locations, users, agents,
operator authorization, audit records, and selected merchant configuration. It
also authorizes and forwards operations owned by processing,
merchant-onboarding, online-txn, auth, and card-present.
Production base URL: https://api.peakgateway.co/management.
Staging base URL: https://staging-api.peakgateway.co/management.
The load balancer removes the /management prefix before the request reaches
the service.
Responsibilities
| Area | Responsibility |
|---|---|
| Tenant model | Organizations, locations, external IDs, access inheritance |
| Users | Portal identities, direct access grants, activation, reset, deactivation |
| Agents | Agent hierarchy, delegated users, organization assignments, rate cards |
| Authorization | Firebase claims, management permissions, tenant-resource checks, impersonation |
| Portal BFF | Authorize, scope, forward, and shape responses from owner services |
| Audit | Persist operator actions and forwarded mutation evidence |
| SSO | SAML provider configuration and JIT provisioning |
| Configuration | Merchant settings and operator-facing integration controls |
Tenant and Role Model
Gateway tenant targeting is organization/location based. Location IDs are opaque strings and remain the concrete payment-execution boundary.
Direct grants are anchors, not expanded access lists:
- platform role:
super_adminoradmin agentAccess:agent_adminoragent_useron an agent subtreeorganizationAccess:organization_adminon an organizationlocationAccess:location_adminorlocation_useron a locationreadonlyfor read-only access
The service expands organization locations and agent descendants from the database on each authorization decision, subject to bounded caches. It does not trust a client-supplied organization/location ID without checking the caller's current accessible set.
See Authorization and Organizations and Locations.
Management as a BFF
The service is deliberately both a domain owner and a proxy tier.
Owner controllers
Owner controllers read and write management-owned data directly: organizations, locations, users, agents, audit, SAML, and management configuration.
Proxy controllers
Proxy controllers terminate portal authentication and follow this sequence:
- Require the operation's
ManagementPermission. - Resolve and clamp the target organization/location/agent from the caller's grants or active impersonation.
- Normalize the body/query so an untrusted client cannot substitute another tenant after authorization.
- Forward through the named
InternalServiceClient. - Persist audit evidence for mutations.
- Return the owner service's result through the BFF contract.
ProxyControllerSupport centralizes ownership-checked read/action seams. New
proxy routes should reuse it rather than open-coding a second authorization
pattern.
| Owner service | Management proxy areas |
|---|---|
| processing | Transactions, settlements, subscriptions, customers, gift cards, tax, reports, credit notes, routing |
| merchant-onboarding | Credential profiles, activation, provisioning jobs |
| online-txn | Checkout/hosted-payment configuration and webhook delivery operations |
| auth | OAuth clients, API keys, device enrollment and entitlements |
| card-present | Bolt fleet, terminal registry, device runtime, app push, easy deploy |
Governance
- Every proxy method needs a management permission and a resource-level tenant check; permission alone is insufficient.
- Management never writes another service's single-owner table.
- Internal owner routes use Cloud Run IAM and must not be added to the public load-balancer map.
- Request DTOs are preferred over untyped maps. Where a transparent proxy must use a map, strip and replace tenant identifiers after authorization.
- A successful downstream mutation followed by failed audit persistence is an explicit uncertain operator outcome, not permission to replay blindly.
Payment ownership
Typed sale, auth, and force-auth requests, plus authenticated setup-intent confirmation, are owned by the online-txn/pay host. Callers must use the pay-host routes:
POST /api/v1/transactions/salePOST /api/v1/transactions/authPOST /api/v1/transactions/force-authPOST /api/v1/setup-intents/{setupIntentId}/confirm
Management exposes only PAN-free virtual-terminal reconciliation at
GET /api/v1/virtual-terminal/reconcile and setup-intent metadata operations.
It never accepts, forwards, or logs card or bank credentials. See the
online-txn service reference for credential validation,
canonical processing, idempotency, and payment authorization requirements.
API Contracts
The curated operator reference covers the current location, user, provisioning, and health contracts:
- Internal operator API reference
websites/support-docs/openapi/internal-api.yaml
Controller annotations and DTOs under
services/management/src/main/kotlin/com/myriad/gateway/management/ remain the
implementation source of truth. Prefer generated OpenAPI over hand-written
request/response examples.
The management surface is broader than the curated support reference. Use controller source and focused tests when working on agents, billing, device fleet, checkout configuration, external capabilities, SAML, audit, or other specialist routes.
Authentication and Authorization
Portal callers send a Firebase ID token. Security filters verify the token,
resolve a typed authenticated principal, and enforce accepted tenant audience.
Controllers declare @RequireManagementPermission; ManagementAuthorizer
performs resource-level checks.
A small set of management routes explicitly accepts OAuth scopes for machine-to-machine integrations. OAuth clients are not promoted into portal roles. Signed token organization claims and endpoint scope checks remain a separate authorization path.
Revocation is bounded by the configured remote-check/cache interval. Grant changes rewrite Firebase claims and revoke refresh tokens; authorization never uses a stale client-provided expanded grant list as authority.
Device and Fleet Boundaries
Fleet visibility and mutation authority are separated:
- management owns portal authorization, configuration, and audit;
- card-present owns terminal/device runtime and orchestration state;
- merchant-onboarding owns processor credentials and activation;
- management proxies to the owner service rather than writing its tables.
This separation is required for device commands, app pushes, XTMS actions, terminal binding, runtime heartbeat views, and Bolt fleet operations.
Webhook Operations
Management owns webhook subscription/configuration and operator replay actions. Online-txn owns ephemeral delivery-attempt and retry state. Domain services persist their state transition before emitting an event. See Event Log and Replay.
Data Ownership
Management-owned table families include organizations, locations/merchant profiles, portal users and access grants, agents and rate configuration, SAML configuration, and management audit data.
The SQLDelight source under libs/schema/src/main/sqldelight/ is authoritative.
Do not use copied DDL or old role/merchant-access examples to plan changes.
Runtime
| Component | Technology |
|---|---|
| Language | Kotlin 2.2 on Java 25 |
| Framework | Spring Boot 4.0.5 |
| Authentication | Firebase Admin SDK, OAuth/JWT exception paths |
| Authorization | ManagementPermission, ManagementAuthorizer, resource ownership checks |
| Database | Cloud Spanner PostgreSQL dialect through SQLDelight/PGAdapter |
| Internal calls | InternalServiceClient with Cloud Run IAM ID tokens |
| Messaging | Cloud Pub/Sub through shared notification/webhook publishers |
Health endpoint: GET /health, publicly reachable as
https://api.peakgateway.co/management/health (and the staging equivalent).