Repository navigation
Getting Started
- Java 17+
- Maven 3.8+
- Docker (for Redis and RabbitMQ)
git clone https://github.com/danielsmori/open-fednow.git
cd open-fednowdocker-compose up -dThis starts:
- Redis on port 6379 — Shadow Ledger real-time balance cache
-
RabbitMQ on port 5672 — maintenance-window transaction queue
- Management UI: http://localhost:15672 (guest / guest)
-
Kafka on port 9092 — optional event streaming bus (KRaft mode, no Zookeeper)
- Only needed if
openfednow.kafka.enabled=true. Start just Redis + RabbitMQ with:docker-compose up -d redis rabbitmq
- Only needed if
The dev profile uses an in-memory H2 database, so no PostgreSQL container is needed locally.
mvn spring-boot:runThe application starts on http://localhost:8080. Wait for Started OpenFedNowApplication in the console output.
curl http://localhost:8080/fednow/health
# → OpenFedNow Gateway — operational./demo/run-demo.shThe script runs all four scenarios automatically and prints pass/fail for each:
| Scenario | What it tests |
|---|---|
| ACSC | Normal payment — core online, accepted and settled |
| RJCT / AM04 | Rejection — insufficient funds |
| ACSP | Provisional acceptance — core timeout, SyncAsyncBridge returns immediately |
| Reconcile |
POST /admin/reconcile — finds unconfirmed Shadow Ledger entries |
| Method | Path | Description |
|---|---|---|
POST |
/fednow/receive |
Receive an inbound pacs.008 credit transfer from FedNow |
POST |
/fednow/send |
Submit an outbound pacs.008 credit transfer to FedNow |
GET |
/fednow/health |
Gateway health check |
POST |
/admin/reconcile |
Trigger a reconciliation run — requires HTTP Basic auth (admin / changeme) |
GET |
/actuator/health |
Detailed health (Redis, RabbitMQ, PostgreSQL, core adapter) |
Full interactive API spec: http://localhost:8080/swagger-ui.html
curl -s -X POST http://localhost:8080/fednow/receive \
-H "Content-Type: application/json" \
-d '{
"messageId": "MSG-001",
"endToEndId": "E2E-001",
"transactionId": "TXN-001",
"interbankSettlementAmount": 250.00,
"interbankSettlementCurrency":"USD",
"creditorAccountNumber": "ACC-12345"
}'{"transactionStatus":"ACSC","originalEndToEndId":"E2E-001","originalTransactionId":"TXN-001"}Control the sandbox response with the creditorAccountNumber prefix:
| Prefix | Response | Reason code |
|---|---|---|
RJCT_FUNDS_ |
RJCT | AM04 — insufficient funds |
RJCT_ACCT_ |
RJCT | AC01 — invalid account |
RJCT_CLOSED_ |
RJCT | AC04 — closed account |
TOUT_ |
ACSP | Core timeout — provisional acceptance |
PEND_ |
ACSP | Core pending — provisional acceptance |
| (any other) | ACSC | Accepted |
curl -s -X POST http://localhost:8080/fednow/receive \
-H "Content-Type: application/json" \
-d '{
"messageId": "MSG-002",
"endToEndId": "E2E-002",
"transactionId": "TXN-002",
"interbankSettlementAmount": 250.00,
"interbankSettlementCurrency":"USD",
"creditorAccountNumber": "RJCT_FUNDS_ACC-67890"
}'{"transactionStatus":"RJCT","originalEndToEndId":"E2E-002","rejectReasonCode":"AM04"}/admin/* requires HTTP Basic authentication (default: admin / changeme):
curl -s -u admin:changeme -X POST http://localhost:8080/admin/reconcile{
"transactionsReplayed": 0,
"discrepanciesDetected": 0,
"reconciliationSuccessful": true,
"summary": "Clean reconciliation: 0 entries confirmed across all accounts"
}transactionsReplayed: 0 is expected in local dev — H2 resets on restart so no bridge-mode entries accumulate. In a PostgreSQL deployment this reflects the actual backlog from the maintenance window.
# Unit tests only (fast, no Docker required)
mvn test -Dgroups=\!integration
# All tests including Testcontainers integration tests
mvn verifyIntegration tests use Testcontainers to spin up PostgreSQL, Redis, RabbitMQ, and (for the Kafka suite) Kafka automatically. All integration tests are annotated with @Testcontainers(disabledWithoutDocker = true) — they are skipped rather than failed when Docker is not available.
- Architecture — how the five layers work together
- Shadow Ledger — what the maintenance-window path actually does
- Known Limitations — H2 vs. PostgreSQL behavior, single-instance assumption
- Configuration Reference — environment variables and Spring profiles