Skip to content

Commit de022f0

Browse files
authored
Merge branch 'main' into feat/227
2 parents 9ff1f27 + 67be593 commit de022f0

829 files changed

Lines changed: 279165 additions & 42287 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/backend-governance.yml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,13 @@ jobs:
3333
run: npm ci
3434

3535
- name: Run governance checks
36-
run: npm run ci:governance
36+
run: npm run ci:governance
37+
38+
- name: Verify OpenAPI documentation
39+
run: |
40+
npm run generate:openapi
41+
if [ -n "$(git status --porcelain openapi.json)" ]; then
42+
echo "❌ openapi.json is out of date. Run 'npm run generate:openapi' locally and commit the changes."
43+
git diff openapi.json
44+
exit 1
45+
fi

.github/workflows/e2e.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,6 @@ jobs:
3131
- name: Install Playwright browsers
3232
run: npx playwright install chromium --with-deps
3333

34-
- name: Build app
35-
run: npm run build
36-
3734
- name: Run E2E tests
3835
run: npm run test:e2e
3936
env:

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,8 @@
1212

1313
# Agents
1414
GEMINI.md
15+
16+
.agents/
17+
.claude/
18+
skills-lock.json
19+
issue.md
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
https://www.figma.com/design/Yja14jB0ZqnCj09eG64A8E/Untitled?node-id=39-2&t=tTIInuSrNVfsd0Sn-1 #238

backend/README.md

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

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

55
## Features
66

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
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
1413

1514
## Quick Start
1615

16+
### Setup
17+
1718
```bash
19+
# Install dependencies
1820
npm install
21+
22+
# Create environment file
1923
cp .env.example .env
24+
```
25+
26+
### Development
27+
28+
```bash
29+
# Start development server with auto-reload
2030
npm run dev
2131
```
2232

23-
The server starts on `http://localhost:3000`.
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+
```
2444

2545
## Configuration
2646

47+
Rate limiting and other settings are configurable via environment variables:
48+
2749
| Variable | Default | Description |
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 |
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 |
3758

3859
## API Endpoints
3960

40-
### Health
61+
### Health Check
4162

42-
```http
63+
```
4364
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+
```
4487
GET /ready
4588
```
4689

47-
### Versioned API
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+
```
48103

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
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+
}
56114
```
57115

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

60-
## Idempotent Mutations
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
61132

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

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`.
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
67139

68-
## Background Jobs
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
69152

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.
153+
# Run tests in watch mode
154+
npm test -- --watch
72155

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

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

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
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
80168

81-
Rollback expectations:
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
82175

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.
176+
## CI/CD Integration
87177

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

90180
```bash
91-
npm run check:migrations
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
92187
```
93188

94-
## Testing
189+
### Docker Deployment
95190

96-
```bash
97-
npm test
98-
npm run build
99-
npm run check:migrations
191+
Example Dockerfile:
192+
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"]
100203
```
101204

102-
## CI
205+
## Monitoring
103206

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

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

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

113220
## License
114221

115-
MIT
222+
MIT

0 commit comments

Comments
 (0)