API gateway and attestation service for Veritasor. Handles revenue data normalization, Merkle proof generation, and on-chain submission to Soroban contracts (integration points are stubbed for the initial version).
- Node.js + TypeScript
- Express for HTTP API
- Planned: PostgreSQL, Redis, gRPC internal services
- Node.js 18+
- npm or yarn
# Install dependencies
npm install
# Run in development (watch mode)
npm run devAPI runs at http://localhost:3000. Use PORT env var to override.
The shared rate limiter in src/middleware/rateLimiter.ts supports explicit route-level buckets. Apply a stable bucket name per sensitive route so bursts against one endpoint do not consume the budget for another endpoint. Auth routes use this for login, refresh, forgot-password, reset-password, and me, while signup keeps its dedicated abuse-prevention limiter.
| Command | Description |
|---|---|
npm run dev |
Start with tsx watch |
npm run build |
Compile TypeScript to dist/ |
npm run start |
Run compiled dist/index.js |
npm run lint |
Run ESLint |
npm run migrate |
Run database migrations |
Routes may be mounted with an /api/v{n} prefix and/or legacy unversioned paths (e.g. /api/attestations). The server still resolves a major version for each request.
- Negotiation: Path segment wins when present; otherwise
X-API-Version,Accept-Version, queryapiVersion/api_version, thenAcceptparameters (version=,api-version=,v=). Default is v1. Unsupported majors fall back to v1 withAPI-Version-Fallback: true. - Response headers:
API-Version(always a supported label), optionalAPI-Version-Fallback, and mergedVaryfor caches. - Spec: docs/specs/api-version-negotiation.md
- Future extensions: Add entries to
SUPPORTED_API_VERSIONSand mount/api/v2routers when ready.
| Method | Path | Description | Auth Required |
|---|---|---|---|
| GET | /api/v1/health |
Health check | No |
| GET | /api/v1/attestations |
List attestations (stub) | User Auth |
| POST | /api/v1/attestations |
Submit attestation (stub) | User Auth |
| GET | /api/v1/businesses/me |
Get user business | User Auth |
| POST | /api/v1/businesses |
Create business | User Auth |
| PATCH | /api/v1/businesses/me |
Update business | User Auth |
The API uses JWT-based authentication. Include the token in the Authorization header:
Authorization: Bearer <your_jwt_token>For business-scoped operations, use the enhanced business authorization middleware:
Authorization: Bearer <your_jwt_token>
x-business-id: <business_id>Security Features:
- JWT token validation with user existence verification
- Business ownership enforcement (users can only access their own businesses)
- Input validation and injection prevention
- Detailed error responses with structured error codes
Error Codes:
MISSING_AUTH(401): Missing or invalid Authorization headerINVALID_TOKEN(401): Invalid, expired, or malformed JWT tokenMISSING_BUSINESS_ID(400): Business ID not provided or invalid formatBUSINESS_NOT_FOUND(403): Business not found or access denied
For detailed documentation, see Business Authorization Boundary Checks.
veritasor-backend/
├── src/
│ ├── db/
│ │ ├── migrations/ # SQL migrations (e.g. 001_create_users_table.sql)
│ │ └── migrate.ts # Migration runner
│ ├── routes/ # health, attestations
│ └── index.ts # Express app entry
├── package.json
└── tsconfig.json
Migrations live in src/db/migrations/ as numbered SQL files (e.g. 001_create_users_table.sql). The runner applies only pending migrations and records them in schema_migrations, so each runs once.
Local database setup (contributors)
The repo does not include database credentials. Install PostgreSQL locally, create a database (and optionally a user), then set DATABASE_URL in your .env using your own username, password, and database name. Example after installing Postgres: create a DB (e.g. createdb veritasor or via your GUI), then use a connection string like postgresql://localhost:5432/veritasor (or with a username/password if you created one).
How to run migrations
- Set
DATABASE_URL(PostgreSQL connection string), e.g. in.env(copy from.env.example). - Run:
npm run migrateOr with the CLI directly:
DATABASE_URL=postgresql://user:pass@localhost:5432/dbname npx tsx src/db/migrate.tsRequires Node 18+ and a running PostgreSQL instance.
Optional .env:
PORT=3000
DATABASE_URL=postgresql://user:password@localhost:5432/veritasor
This directory is its own git repository. To push to your remote:
git remote add origin <your-backend-repo-url>
git push -u origin main