Skip to content

Commit 34e48b4

Browse files
authored
Merge branch 'main' into feat/keyboard-shortcuts
2 parents 56c39fc + fd9e8a0 commit 34e48b4

20 files changed

Lines changed: 1397 additions & 279 deletions
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: Backend Governance
2+
3+
on:
4+
pull_request:
5+
paths:
6+
- 'backend/**'
7+
- '.github/workflows/backend-governance.yml'
8+
push:
9+
branches:
10+
- main
11+
paths:
12+
- 'backend/**'
13+
- '.github/workflows/backend-governance.yml'
14+
15+
jobs:
16+
backend-governance:
17+
runs-on: ubuntu-latest
18+
defaults:
19+
run:
20+
working-directory: backend
21+
steps:
22+
- name: Checkout
23+
uses: actions/checkout@v4
24+
25+
- name: Setup Node
26+
uses: actions/setup-node@v4
27+
with:
28+
node-version: '20'
29+
cache: npm
30+
cache-dependency-path: backend/package-lock.json
31+
32+
- name: Install dependencies
33+
run: npm ci
34+
35+
- name: Run governance checks
36+
run: npm run ci:governance

backend/README.md

Lines changed: 62 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -1,222 +1,115 @@
11
# YieldVault Backend API
22

3-
Express.js backend server for YieldVault Stellar RWA platform with rate limiting and health monitoring.
3+
Express.js backend for the YieldVault Stellar RWA platform.
44

55
## Features
66

7-
- **Health Check Endpoint** (`/health`) - Real-time service health status
8-
- **Readiness Endpoint** (`/ready`) - Dependency status for deployment orchestration
9-
- **Rate Limiting** - Per-IP and per-API-key rate limiting to prevent abuse
10-
- **Dependency Monitoring** - Checks for cache and Stellar RPC availability
11-
- **Error Handling** - Consistent JSON error responses
12-
- **TypeScript** - Full type safety with TypeScript
7+
- Health and readiness endpoints
8+
- Rate limiting for public API routes
9+
- Versioned API surface under `/api/v1`
10+
- Replay-safe mutations via idempotency keys
11+
- Background job retry policy and dead-letter metrics
12+
- Migration safety checks in CI
13+
- TypeScript with Jest test coverage
1314

1415
## Quick Start
1516

16-
### Setup
17-
1817
```bash
19-
# Install dependencies
2018
npm install
21-
22-
# Create environment file
2319
cp .env.example .env
24-
```
25-
26-
### Development
27-
28-
```bash
29-
# Start development server with auto-reload
3020
npm run dev
3121
```
3222

33-
The server will start on `http://localhost:3000`.
34-
35-
### Production
36-
37-
```bash
38-
# Build TypeScript
39-
npm run build
40-
41-
# Start production server
42-
npm start
43-
```
23+
The server starts on `http://localhost:3000`.
4424

4525
## Configuration
4626

47-
Rate limiting and other settings are configurable via environment variables:
48-
4927
| Variable | Default | Description |
50-
|----------|---------|-------------|
51-
| `PORT` | 3000 | Server port |
52-
| `NODE_ENV` | development | Environment mode |
53-
| `RATE_LIMIT_WINDOW_MS` | 900000 | Global rate limit window (15 min) |
54-
| `RATE_LIMIT_MAX_REQUESTS` | 100 | Global requests per window |
55-
| `API_RATE_LIMIT_WINDOW_MS` | 60000 | API rate limit window (1 min) |
56-
| `API_RATE_LIMIT_MAX_REQUESTS` | 30 | API requests per window |
57-
| `STELLAR_RPC_URL` | https://soroban-testnet.stellar.org | Stellar RPC endpoint |
28+
| --- | --- | --- |
29+
| `PORT` | `3000` | Server port |
30+
| `NODE_ENV` | `development` | Runtime mode |
31+
| `RATE_LIMIT_WINDOW_MS` | `900000` | Global rate limit window |
32+
| `RATE_LIMIT_MAX_REQUESTS` | `100` | Global requests per window |
33+
| `API_RATE_LIMIT_WINDOW_MS` | `60000` | API rate limit window |
34+
| `API_RATE_LIMIT_MAX_REQUESTS` | `30` | API requests per window |
35+
| `IDEMPOTENCY_KEY_TTL_MS` | `86400000` | Replay window for mutation requests |
36+
| `STELLAR_RPC_URL` | `https://soroban-testnet.stellar.org` | Stellar RPC endpoint |
5837

5938
## API Endpoints
6039

61-
### Health Check
40+
### Health
6241

63-
```
42+
```http
6443
GET /health
65-
```
66-
67-
Returns service health status with dependency checks.
68-
69-
**Response (200 OK):**
70-
```json
71-
{
72-
"status": "healthy",
73-
"timestamp": "2026-03-26T10:30:00.000Z",
74-
"uptime": 3600.5,
75-
"environment": "development",
76-
"checks": {
77-
"api": "up",
78-
"cache": "up",
79-
"stellarRpc": "up"
80-
}
81-
}
82-
```
83-
84-
### Readiness Check
85-
86-
```
8744
GET /ready
8845
```
8946

90-
Returns service readiness state. Checks all critical dependencies before reporting ready.
91-
92-
**Response (200 OK - Ready):**
93-
```json
94-
{
95-
"ready": true,
96-
"timestamp": "2026-03-26T10:30:00.000Z",
97-
"dependencies": {
98-
"cache": true,
99-
"stellarRpc": true
100-
}
101-
}
102-
```
47+
### Versioned API
10348

104-
**Response (503 Unavailable - Not Ready):**
105-
```json
106-
{
107-
"ready": false,
108-
"timestamp": "2026-03-26T10:30:00.000Z",
109-
"dependencies": {
110-
"cache": false,
111-
"stellarRpc": false
112-
}
113-
}
49+
```http
50+
GET /api/v1/vault/summary
51+
GET /api/v1/transactions
52+
GET /api/v1/portfolio/holdings
53+
GET /api/v1/vault/history
54+
POST /api/v1/vault/deposits
55+
GET /api/v1/ops/job-metrics
11456
```
11557

116-
### Rate Limit Exceeded
58+
Legacy `/api/*` routes redirect to `/api/v1/*` with `308 Permanent Redirect`.
11759

118-
```
119-
Status: 429 Too Many Requests
120-
```
121-
122-
```json
123-
{
124-
"error": "Too many requests",
125-
"status": 429,
126-
"message": "Rate limit exceeded. Please try again later.",
127-
"retryAfter": 1711432200000
128-
}
129-
```
130-
131-
## Rate Limiting
60+
## Idempotent Mutations
13261

133-
### Global Rate Limiting
62+
Mutation endpoints require `x-idempotency-key`.
13463

135-
Applied to all requests except `/health` and `/ready`:
136-
- Window: 15 minutes (configurable)
137-
- Max: 100 requests per window (configurable)
138-
- Per: IP address
64+
- Same key + same payload returns the original response.
65+
- Same key + different payload returns `409 Conflict`.
66+
- TTL is controlled by `IDEMPOTENCY_KEY_TTL_MS`.
13967

140-
### API Endpoint Rate Limiting
141-
142-
Stricter limits for API endpoints (e.g., `/api/vault/summary`):
143-
- Window: 1 minute (configurable)
144-
- Max: 30 requests per window (configurable)
145-
- Per: API key (from `x-api-key` header) or IP address
146-
147-
## Testing
148-
149-
```bash
150-
# Run all tests
151-
npm test
68+
## Background Jobs
15269

153-
# Run tests in watch mode
154-
npm test -- --watch
70+
Job execution uses explicit retry policies per job class with exponential backoff.
71+
Failed jobs are written to a dead-letter sink and surfaced through job metrics.
15572

156-
# Run with coverage
157-
npm test -- --coverage
158-
```
73+
## Migration Safety
15974

160-
## Issues Addressed
75+
The CI scanner flags:
16176

162-
### Issue #145: Rate Limiting
163-
- ✅ Global rate limiting per IP
164-
- ✅ Per-user/API-key rate limiting
165-
- ✅ Configurable via environment variables
166-
- ✅ Clear 429 responses with retry information
167-
- ✅ Tests included for rate limiting behavior
77+
- irreversible schema changes such as `DROP` and `TRUNCATE`
78+
- long-running or locking migration patterns
79+
- schema changes that add indexed columns without an index declaration
16880

169-
### Issue #148: Health & Readiness Endpoints
170-
-`/health` endpoint for service health
171-
-`/ready` endpoint for deployment readiness
172-
- ✅ Dependency health checks (cache, RPC)
173-
- ✅ CI smoke test setup via npm scripts
174-
- ✅ Consistent response formats
81+
Rollback expectations:
17582

176-
## CI/CD Integration
83+
- Prefer additive schema changes.
84+
- Add indexes before deploying code that depends on them.
85+
- Avoid destructive drops in the same deploy as a data migration.
86+
- Document manual rollback steps when a migration cannot be reversed automatically.
17787

178-
### Smoke Test (CI Pipeline)
88+
Run the scanner locally with:
17989

18090
```bash
181-
# Build and start server
182-
npm run test:smoke
183-
184-
# The server will start in background, ready for health checks
185-
# Call: curl http://localhost:3000/health
186-
# Call: curl http://localhost:3000/ready
91+
npm run check:migrations
18792
```
18893

189-
### Docker Deployment
190-
191-
Example Dockerfile:
94+
## Testing
19295

193-
```dockerfile
194-
FROM node:20-alpine
195-
WORKDIR /app
196-
COPY package*.json ./
197-
RUN npm ci --only=production
198-
COPY dist ./dist
199-
EXPOSE 3000
200-
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
201-
CMD node -e "require('http').get('http://localhost:3000/health', (r) => r.statusCode === 200 ? process.exit(0) : process.exit(1))"
202-
CMD ["npm", "start"]
96+
```bash
97+
npm test
98+
npm run build
99+
npm run check:migrations
203100
```
204101

205-
## Monitoring
102+
## CI
206103

207-
Headers returned in responses:
104+
The backend governance workflow runs:
208105

209-
- `RateLimit-Limit` - Request limit
210-
- `RateLimit-Remaining` - Requests remaining
211-
- `RateLimit-Reset` - Reset timestamp
106+
- `npm run lint`
107+
- `npm run test`
108+
- `npm run build`
109+
- `npm run check:migrations`
212110

213-
Example:
214-
```
215-
RateLimit-Limit: 100
216-
RateLimit-Remaining: 95
217-
RateLimit-Reset: 1711432200
218-
```
111+
See [`.github/workflows/backend-governance.yml`](../.github/workflows/backend-governance.yml).
219112

220113
## License
221114

222-
MIT
115+
MIT

backend/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
"test": "jest",
1111
"test:smoke": "npm run build && npm run start &",
1212
"lint": "eslint src",
13-
"format": "prettier --write src"
13+
"format": "prettier --write src",
14+
"check:migrations": "node scripts/check-migrations.js",
15+
"ci:governance": "npm run lint && npm run test && npm run build && npm run check:migrations"
1416
},
1517
"keywords": [
1618
"stellar",

0 commit comments

Comments
 (0)