Skip to content

Hector-Ha/Interlock

Repository files navigation

Interlock logo

Interlock

A secure open-banking app for bank linking, transaction sync, ACH transfers, and P2P payments.

Interlock is a full-stack fintech monorepo that connects Plaid banking data and Dwolla ACH payments through a Next.js frontend and a Go backend. Local runtime, CI, deployment, and database migrations are owned by server-go/.

At a Glance

  • Frontend: Next.js 16, React 19, TypeScript, Tailwind CSS 4, Zustand, Radix UI, Chart.js
  • Backend: Go, Chi, pgx, PostgreSQL
  • Integrations: Plaid, Dwolla, SendGrid, Sentry
  • Testing: Vitest, React Testing Library, Go tests
  • Deployment: Docker Compose, GHCR images, EC2-oriented deploy script

Features

Area Status Notes
Authentication Complete Sessions, refresh tokens, email verification, password reset, account lockout
Bank linking Complete Plaid Link, token exchange, update mode, balance sync
Transactions Complete Sync, filters, categories, dashboard summaries
ACH transfers Complete Dwolla funding sources, transfer creation, status tracking, cancellation
P2P transfers Complete Recipient search, send/receive flows, notifications
Notifications Complete In-app notifications and preferences
Security Complete Rate limits, secure headers, PII encryption, webhook verification
Observability Complete Sentry, structured logs, health checks, metrics endpoint
Go backend migration Complete Native runtime, CI, deployment, and migrations use server-go/

Architecture

client/        Next.js app and browser-facing API client
server-go/     Go backend, native API handlers, migrations, and integration code
docs/          Deployment and observation notes
performance/   k6 performance scripts

The local Docker topology runs PostgreSQL and the Go backend on :8080.

Prerequisites

  • Bun v1.3+
  • Go 1.26+ for server-go
  • PostgreSQL 16+
  • Docker and Docker Compose, optional but recommended for local services

Note

Use Bun for JavaScript dependencies and scripts in this repo. Prefer bun over pnpm or npm, and bunx over npx.

Quick Start

bun install
cp .env.example .env

Update the root .env with database, JWT, encryption, Plaid, Dwolla, SendGrid, and Sentry values as needed. This is the single env file for the monorepo. For local development, the most important values are:

DATABASE_URL=postgresql://postgres:password@localhost:5432/interlock
JWT_SECRET=replace-with-at-least-32-characters
ENCRYPTION_KEY=replace-with-32-characters
CLIENT_URL=http://localhost:3000
NEXT_PUBLIC_API_URL=http://localhost:8080

The Go backend loads .env when started from the repo root and ../.env when started from server-go/, without overriding existing shell variables. Run migrations through the root script so the root .env is loaded before the migration subcommand.

Start local infrastructure:

docker compose up -d postgres

Apply Go-owned database migrations:

bun run migrate

Run the app:

bun run dev
  • Client: http://localhost:3000
  • API: http://localhost:8080

Development Commands

# Install all workspace dependencies
bun install

# Run client and Go backend
bun run dev

# Backward-compatible alias for the Go backend dev script
bun run dev:go-edge

# Client only
bun run --cwd client dev

# Go backend only
go run ./server-go/cmd/interlock-go

# Apply Go database migrations
bun run migrate

# Go admin/debug CLI
bun run admin -- users

go run ./server-go/cmd/interlock-go loads the root .env for normal server startup. The migration subcommand reads the process environment directly, so prefer bun run migrate locally or Docker Compose/deploy commands in container workflows.

Legacy admin/debug workflows now run through bun run admin -- <command>. See docs/ADMIN_RUNBOOK.md.

Testing

# Client tests
bun run --cwd client test

# Client lint
bun run --cwd client lint

# Go formatting check
cd server-go && test -z "$(gofmt -l .)"

# Go tests
cd server-go && go test ./...

Performance smoke tests live in performance/k6/backend-hotpaths.js and expect a running backend.

Go Backend

server-go is the backend runtime. Native handlers cover health, metrics, auth, Plaid, banks/accounts, transactions, transfers, P2P, notifications, and webhooks. Database migrations are embedded in the Go binary and run through bun run migrate locally or server-go migrate up in deployment containers.

Docker

# Local database only
docker compose up -d postgres

# Local backend topology: Postgres and Go backend
docker compose up -d postgres server-go

# Optional tools
docker compose --profile tools up studio
docker compose --profile tools run semgrep

Production-oriented Compose and deployment files are docker-compose.prod.yml and deploy.sh. Server images are built and pushed to GHCR by .github/workflows/build-server.yml.

Security Notes

  • Do not commit real .env files or production credentials.
  • PII fields are encrypted with AES-256-GCM-compatible helpers across the TypeScript and Go runtimes.
  • Passwords use bcrypt, auth uses JWT access tokens plus refresh-token rotation, and sensitive routes are rate-limited.
  • Dwolla webhooks use HMAC verification and idempotency handling.
  • Keep JWT_SECRET, ENCRYPTION_KEY, Plaid keys, Dwolla keys, SendGrid keys, GHCR PATs, and Sentry tokens out of logs and docs.

Useful Docs

  • docs/DEPLOYMENT.md for deployment steps
  • docs/client-observation.md for frontend observations
  • docs/server-observation.md for backend observations
  • server-go/README.md for Go backend details
  • server-go/contracts/GO_MIGRATION_STATUS.md for migration status

About

Interlock is a secure, monolithic REST API banking application built with Express.js, PostgreSQL, and Redis, integrating Plaid and Dwolla for financial data and payments.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors