- ๐ What is this repo?
- ๐ Quick Start
- ๐๏ธ Metadata Architecture
- ๐ Documentation
- ๐ ๏ธ Manual Commands (optional)
- ๐ฅ๐ฌ Karate Tests
- ๐ค Contributing
- ๐ License
The backend infrastructure for SafeTrust โ a decentralized P2P escrow platform for rental transactions on the Stellar blockchain. This repo contains:
- โก Hasura GraphQL Engine โ auto-generated API with JWT auth and row-level permissions
- ๐ PostgreSQL โ multi-tenant schema (
safetrust+hotel_industry) - ๐ช Webhook service โ Node/Express, handles Firebase auth sync and escrow lifecycle events
- ๐ Migrations + seeds โ versioned schema and dev data for both tenants
| Tool | Version |
|---|---|
| Docker + Docker Compose | โฅ 24 |
| Hasura CLI | โฅ 2.x |
| curl | any |
๐ก Windows Note: Run
bin/startinside WSL (Ubuntu) or Git Bash.
cp .env.example .env
Fill in .env before running anything:
POSTGRES_PASSWORD=your_postgres_password
# Must be valid JSON, key โฅ 32 characters for HS256
HASURA_GRAPHQL_JWT_SECRET={"type":"HS256","key":"replace-with-min-32-char-secret-here"}
HASURA_EVENT_SECRET=your_event_secret
โ ๏ธ HASURA_GRAPHQL_JWT_SECRETmust be valid JSON with a key of at least 32 characters.startwill fail if this is malformed.
bin/start tenant-name tenant-name
start runs in order:
| Step | Action |
|---|---|
| 1 | Start postgres, graphql-engine, webhook containers |
| 2 | Poll GET /healthz until Hasura is ready (up to 3 min) |
| 3 | Build and deploy tenant metadata for all tenants |
| 4 | Apply all migrations per tenant |
| 5 | Reload Hasura metadata |
| 6 | Apply seed data per tenant in parallel, with one transaction per seed file |
Seed files are applied directly with PostgreSQL and ON_ERROR_STOP=1. Each file
is wrapped in BEGIN/COMMIT, so a failed file rolls back completely; the two
independent tenants run concurrently. Seed inserts use conflict-safe or
stable-key cleanup patterns, making bin/start safe to rerun without
docker compose down -v.
Set SEED_CHUNK_SIZE in .env to tune the configured seed batch size (default
500).
Target a specific tenant:
bin/start safetrust # one tenant
bin/start safetrust hotel_industry # both explicitly
bin/start --reset safetrust
--reset removes the Docker volumes before starting, so tenant data is
recreated by migrations and seeds. To recreate the containers while keeping
the database volumes, use:
bin/start --restart safetrust# Rollback safetrust migrations:
hasura migrate apply \
--endpoint http://localhost:8080 \
--admin-secret myadminsecretkey \
--database-name safetrust \
--down all
# Rollback hotel_industry migrations:
hasura migrate apply \
--endpoint http://localhost:8080 \
--admin-secret myadminsecretkey \
--database-name hotel_industry \
--down all
metadata/
โโโ base/ โ shared Hasura config across all tenants
โโโ tenants/
โ โโโ safetrust/ โ apartments, escrows, users, wallets
โ โโโ hotel_industry/ โ hotels, rooms, reservations, escrow_transactions
โโโ build/ โ generated output (tenants merged with base), ready to deploy
โโโ build-metadata.sh
โโโ deploy-tenant.sh
โโโ setup-tenant.sh โ runs build + deploy in one command โ
bin/starthandles all of these automatically. Use these only when targeting a specific step in isolation.
cd metadata
./setup-tenant.sh safetrust --endpoint http://localhost:8080 --admin-secret myadminsecretkey
hasura migrate apply \
--database-name safetrust \
--endpoint http://localhost:8080 \
--admin-secret myadminsecretkey
hasura migrate apply \
--database-name safetrust \
--version <timestamp> \
--type up \
--endpoint http://localhost:8080 \
--admin-secret myadminsecretkey
hasura seed apply \
--database-name safetrust \
--endpoint http://localhost:8080 \
--admin-secret myadminsecretkey
For the same transactional behavior as startup, use bin/start for seed
application rather than invoking hasura seed apply directly.
bin/deploy_init is an experimental benchmarking tool for evaluating parallel deployment vs the canonical sequential path.
Contributors run both scripts from identical starting conditions and record the JSON output:
docker compose down -v
bin/start safetrust hotel_industry # canonical path
# record: tests/results/deploy_timings_sequential_N2.json
docker compose down -v
bin/start # infrastructure only
bin/deploy_init safetrust hotel_industry # PARALLEL_DEPLOY=false
# record: tests/results/deploy_init_timings_sequential_N2.jsondocker compose down -v
bin/start
PARALLEL_DEPLOY=true bin/deploy_init safetrust hotel_industry
# record: tests/results/deploy_init_timings_parallel_N2.json# Simulate 5 tenants by deploying same 2 tenants with 3 aliases
# This validates the parallel execution model without requiring real tenant data
docker compose down -v
bin/start
PARALLEL_DEPLOY=true bin/deploy_init \
safetrust hotel_industry safetrust hotel_industry safetrust
# record: tests/results/deploy_init_timings_parallel_N5.jsonIn-depth guides live in docs/.
| Document | What it covers |
|---|---|
| SafeTrust Schema Migration Strategy | Why SafeTrust tables moved from public to the safetrust schema, plus the deployment and rollback sequences |
API tests using the Karate framework, running in Docker.
bin/test # start karate testingReports are generated at:
tests/results/karate-summary.htmltests/results/karate-tags.html
Add new tests: Create .feature files in tests/karate/features/ โ picked up automatically.
Config files:
tests/karate/src/test/resources/karate-config.jsdocker-compose-test.ymlDockerfile.test
๐
bin/testrunsdocker compose -f docker-compose-test.yml run --rm --build karateinternally.
bin/startmust complete without errors.- No raw SQL outside of
migrations/โ all schema changes go through versioned migration files. - Never edit a migration that has already been applied โ add a new one instead.
- Link the issue your PR closes.
Branch naming: feat/<issue-number>-short-description ยท fix/<issue-number>-short-description
- ๐ Contributing Guide
- ๐ฟ Git Guidelines
ยฉ 2026 SafeTrust. Released under the MIT License.
