Connectors & Extensibility
How the G2P Bridge core stays standard while connectors are pluggable per deployment
The G2P Bridge integrates with the outside world through connectors — bank connectors, the ID→FA mapper, notifiers, and the geo/agency/warehouse allocators for in-kind flows. These are the one part of the Bridge that legitimately varies per deployment (every programme has its own sponsor bank, its own notifier, sometimes its own registry). Everything else — the disbursement engine, the APIs, the Celery pipeline, the data model — is the same for everyone.
This page describes how the codebase is organised so that adopters can supply their own connectors without ever forking or modifying the Bridge platform.
1. Repository structure
The platform — core/ (models, partner-api, bene-portal-api, celery beat + workers), the Docker builds, the Helm chart, and CI. It also bundles the demo Example Bank.
OpenG2P only — standard, versioned, never forked by adopters
The six connector packages: interfaces + DTOs + config-driven factories + the reference implementations (SPAR mapper, Example Bank connector, Novu notifier, …).
OpenG2P for the reference set; adopters fork/copy freely
your connector repo
One small package implementing a connector interface, plus a ~4-line Dockerfile.
the adopter
g2p-bridge builds everything and deploys nothing you have to touch. The connectors repo holds only Python source; the Bridge's Celery image pulls the reference connectors from it at build time (by git ref) and bakes them in.
2. Why the split
Previously the connectors lived inside g2p-bridge (in an extensions/ folder). To run a different bank or notifier, an adopter had to fork the whole Bridge repo, edit a factory, and rebuild — which meant they were now carrying a modified copy of the entire platform, could not cleanly take upstream fixes, and were effectively unsupportable ("what did you change?").
The goals of the split:
Keep core standard and tightly versioned. Adopters consume it as an immutable, version-pinned dependency — they cannot tamper with it just because they need a different connector.
Make connectors the only variable part, isolated in their own repo, safe to fork or copy.
Let adopters build their own image (core + their connector) as a thin overlay, not a fork — so support has a crisp boundary.
3. How the split works
Two mechanisms make this possible with no change to core when a connector changes.
a) Core consumes connectors by git ref
The Bridge's Celery image installs core/* from local source, then pulls the reference connectors from g2p-bridge-connectors by git ref — the same way it already pulls openg2p-fastapi-common:
The reference connectors are thus baked into the published Celery image, which doubles as the base image adopters extend.
b) Connectors are selected by config, not code
Each connector package exposes a factory and an Initializer. The Initializer registers the implementation named in config; the factory returns whatever was registered (via the framework's interface-based component lookup). Nothing references a concrete implementation by name, so adding one needs no code edit — not in core, not even in the connectors repo.
Single-implementation connectors (mapper, notification, agency, warehouse) read one dotted path,
…_IMPL.Keyed connectors (bank → sponsor bank code; geo → target registry) read a
{key: dotted-path}map,…_IMPLS, and the factory dispatches by key.
bank
G2P_BRIDGE_BANK_CONNECTORS_IMPLS
{"EXAMPLE-BANK": "…ExampleBankConnector"}
mapper
G2P_BRIDGE_MAPPER_CONNECTORS_IMPL
…SPARMapper
notification
G2P_BRIDGE_NOTIFICATION_CONNECTORS_IMPL
…NovuNotifier
geo
G2P_BRIDGE_GEO_RESOLVER_IMPLS
{"farmer": "…FarmerGeoResolverImpl"}
agency
G2P_BRIDGE_AGENCY_ALLOCATOR_IMPL
…AgencyAllocatorRefImpl
warehouse
G2P_BRIDGE_WAREHOUSE_ALLOCATOR_IMPL
…WarehouseAllocatorRefImpl
The extend-the-base-image pattern
The adopter's image inherits the entrypoint, the core install, and all the build logic from the base image — they can only add a layer, never modify the platform.
Which connectors version is in an image
Because the connectors are pulled by git ref, every published Celery image records the exact connectors commit it was built from — the CI resolves the pinned ref (e.g. develop) to a commit SHA at build time, passes that SHA as the build arg (so the build is reproducible), and stamps it as an OCI image label. You can therefore read the connectors commit straight off the image, without running it:
The relevant labels:
org.openg2p.pin.g2p-bridge-connectors-ref
connectors commit SHA baked into this image
org.openg2p.pin.fastapi-common-ref / org.openg2p.pin.spar-ref
the other pinned dependency SHAs
org.opencontainers.image.revision
the g2p-bridge (platform) commit the image was built from
org.opencontainers.image.version
the published version (e.g. 0.0.0-develop.41)
The SHA is frozen at build time, so a given image tag always resolves to the same connectors commit even after develop moves on. As a second, always-exact source, each connector package inside the image also carries pip's PEP 610 record — …/openg2p_g2p_bridge_bank_connectors-*.dist-info/direct_url.json — whose commit_id is the same SHA.
4. Writing and integrating a new connector
An adopter never forks core. The end-to-end steps:
Implement the interface in your own small package, depending on the relevant connector package (in
g2p-bridge-connectors) for the interface + DTOs. E.g. a bank connector subclassesBankConnectorInterfaceand implementscheck_funds/block_funds/disburse_funds/ etc.Build a derived image from the published Celery image:
Select it via config (env vars / Helm values). Keyed connectors register under their dispatch key:
Single-impl connectors point
…_IMPLat your class.Deploy with the standard Bridge Helm chart, overriding only the Celery
image.tagto your derived image. The APIs, the chart, and every other image stay the Bridge's standard, unmodified builds.
That's the whole contract: implement the interface, install your package onto the base image, name it in config. No fork, no core change, a thin and supportable overlay.
See the connector interface guides under Tech Guides (e.g. the Bank Connector Interface Guide) for the method-by-method contract of each interface, and the g2p-bridge-connectors README for a copy-paste quickstart.
Last updated
Was this helpful?