Rail Registry Blueprint

Pluggable RailAdapter registry — admin API to add/swap rails, routing policy engine that selects a rail per payment by amount/region/merchant

   
Feature rail-registry
Category Payment
Version 1.0.0
Tags rail, registry, routing, policy, pluggable, adapter
YAML Source View on GitHub
JSON API rail-registry.json

Actors

ID Name Type Description
pgw Payments Gateway system Caller — asks registry to route each payment
admin Admin operator human Registers / swaps rail adapters via admin API
adapter RailAdapter plugin external Implementation of the rail contract (PayShap, Visa, RTGS, sandbox, …)

Fields

Name Type Required Label Description
rail_id text Yes Rail identifier (e.g. payshap, visa, sandbox)  
adapter_module text Yes Module path implementing the RailAdapter contract  
priority number Yes Tie-break priority when policies match multiple rails  
enabled boolean Yes Whether the rail is currently routable  
routing_policy json Yes Policy expression (amount/currency/region/merchant rules)  

Rules

  • contract: MUST: every rail adapter implements authorize(), capture(), refund(), status(), supports_currency(), MUST: registering a rail does NOT require device firmware updates
  • routing: MUST: routing evaluates policies in priority order; first match wins, MUST: disabled rails are never selected even when policy matches
  • admin: MUST: rail registration requires operator role + mTLS-authenticated admin session

Outcomes

Unauthorized (Priority: 1) — Error: RAIL_UNAUTHORIZED

Given:

  • admin session missing or insufficient role

Result: 401 — operator auth required

Invalid_policy (Priority: 5) — Error: RAIL_INVALID_POLICY

Given:

  • routing_policy fails schema validation

Result: 400 — policy rejected

Duplicate (Priority: 10) — Error: RAIL_ALREADY_EXISTS

Given:

  • rail_id already registered

Result: 409 — use PUT to update instead

Rail_registered (Priority: 100)

Given:

  • operator role verified
  • adapter_module is in the signed allowlist
  • routing_policy parses and validates

Then:

  • create_record
  • emit_event event: rail.registered

Result: Rail available for routing on next payment

Errors

Code Status Message Retry
RAIL_INVALID_POLICY 400 Routing policy is invalid No
RAIL_UNAUTHORIZED 401 Admin authentication required No
RAIL_ALREADY_EXISTS 409 A rail with that id already exists No

Events

Event Description Payload
rail.registered    
rail.disabled    
rail.routing.decision    
Feature Relationship Reason
payments-gateway-api required PGW is the sole caller of the registry during routing
payshap-rail recommended First-class ZA rail adapter
sandbox-rail-adapter recommended Mock rail used for sandbox and demos