feat(auth): add API key authentication with rate limiting (#594)#2
Open
fytgian wants to merge 132 commits into
Open
feat(auth): add API key authentication with rate limiting (#594)#2fytgian wants to merge 132 commits into
fytgian wants to merge 132 commits into
Conversation
- apiKeyService: key generation (psk_ prefix, 32-byte random), SHA-256 hashing, validation, per-key sliding-window rate limiting, rotation (revoke + re-issue), revocation by id, usage tracking, owner listing - apiKeys router: POST /api-keys (create), GET /api-keys (list), POST /api-keys/:id/rotate, DELETE /api-keys/:id (revoke), GET /api-keys/:id/usage — all with swagger JSDoc - auth middleware: replaced env-var key list with apiKeyService validation + per-key rate limit check (429 on breach); JWT path unchanged - server.js: mount /v1/api/api-keys router
- POST /v1/api/streams/:stream_id/top-up accepts employer + amount - Validates stream exists via get_stream contract call - Rejects top-up if stream status is not Active - Calls top_up(employer, stream_id, amount) on Soroban contract - Invalidates stream cache after successful top-up - Full input validation (stream_id, employer address, amount > 0) - Swagger JSDoc documented
- templateService: in-memory CRUD, createFromStream (strips employer/employee), share toggle, owner-scoped list that includes shared+default templates, seeded default templates (Monthly Salary USDC, Weekly Contractor USDC) - streamTemplates router: POST /stream-templates (create), GET (list), GET /:id, PATCH /:id (update), DELETE /:id, POST /:id/share, POST /:id/create-stream (instantiate with optional overrides) - server.js: mount /v1/api/stream-templates behind authMiddleware
- Add services/balance/balance.js with calculateBalance() and calculateBalanceByDuration() - Account for pause periods via calcPausedSeconds() - Support daily, weekly, monthly, and custom duration types - Handle leap years and DST via UTC Date arithmetic - Handle edge cases: cliff, stop_time, cancelled/exhausted streams, partial periods - Add 16 unit tests covering all acceptance criteria Closes Vera3289#498
- Add MigrationRunner class with versioned up/down migrations - Before/after validation hooks per migration step - Rollback support (roll back newest-first to target version) - Append-only audit trail (file + DB migration_history table) - User notification hooks (migration_started/success/failed/rollback_*) - Zero-downtime design: migrations operate on data arrays, no table locks - Example migration: 0002_add_cliff_delegate.js - 7 unit tests covering all acceptance criteria Closes Vera3289#505
- Add scripts/deploy-rollback.sh: automated blue-green rollback - Health check (configurable retries/interval) before traffic switch - Automatic slot calculation (blue↔green) - Deployment history tracking (deployment-history.json) - Rollback notification webhook support - Dry-run mode for testing - Add .github/workflows/deploy-rollback.yml: manual + automated trigger - Callable from other workflows on health-check failure - Uploads deployment history as artifact - Add services/deployment/rollback.test.js: 10 unit tests - Slot calculation, health check retry logic, history recording Closes Vera3289#513
- Add SnapshotStore class with configurable interval and retention - checkpoint(): periodic snapshot (skips if interval not elapsed) - forceCheckpoint(): on-demand snapshot for withdrawals/status changes - query(): historical query with optional time range filter - queryAt(): point-in-time recovery lookup (most recent snapshot ≤ ts) - cleanup(): prune snapshots older than a given timestamp - MemoryStorage backend (swap for DB/file backend in production) - Compact snapshot format: only 7 essential fields (minimal overhead) - 11 unit tests covering all acceptance criteria Closes Vera3289#503
- Emit dedicated paused/resumed/cancelled events with employer address for off-chain indexing - Remove generic stream_status_changed in favour of typed event fns - Add edge-case tests: double-pause, resume-active, wrong-employer auth, cancel-while-paused payout
- All events carry complete state for off-chain indexing: stream_created includes token, deposit, rate, stop_time withdrawn includes total_withdrawn cumulative topped_up includes new total deposit stream_cancelled includes employee_payout and employer_refund - Dedicated typed events per operation (no generic status event) - Consistent topic convention: (event_name, stream_id)
- Add per-user and global stream creation rate limits with sliding window - Configurable limits and window duration via admin functions - Admin can exempt trusted addresses from rate limits - Add DataKey variants: UserRateCount, UserRateWindow, GlobalRateCount, GlobalRateWindow, RateLimitUser, RateLimitGlobal, RateLimitWindow, RateLimitExempt - Add ERR_RATE_LIMIT (E005) error code - Fix pre-existing: define StreamParams, add Vec import, fix claimable_at, add locked field to batch stream creation, add MinDeposit DataKey - Tests: user limit exceeded, window reset, exempt bypass
- Multi-stage Dockerfile: base, builder (WASM), test, dev - Dev stage installs cargo-watch for hot-reload on source changes - docker-compose: build, test, and dev services - dev service mounts source + two cache volumes (registry, target) - .dockerignore excludes target/, .git/, *.wasm, docs to minimise build context sent to the daemon
- Add balance.rs with BalanceSnapshot contracttype - Expose balance_snapshot() on StreamContract - Account for paused state, stop_time cap, vested/unvested split - Add remaining_duration(), daily_rate(), monthly_rate() helpers - Fix duplicate MinDeposit variant in DataKey enum - Fix missing pending-admin imports in lib.rs - Unit tests for all calculation paths
- Add services/cache/ crate with CacheClient backed by ConnectionManager
- TTL config per data type: stream=30s, user_stats=60s, token_info=300s
- Cache key strategy: ps:stream:{id}, ps:user:{addr}:stats, ps:token:{addr}
- Cache-aside get_or_load() helper with transparent fallback on Redis errors
- Cache invalidation via invalidate() on updates
- Hit/miss metrics via atomic counters
- Cache warming on startup via warm_streams()
- Unit tests for key helpers and metrics
- Add services/search/ crate (paystream-search) - StreamFilter: recipient substring, token, status, amount range, date range - Combined filters, pagination (page/page_size), sorting (id/deposit/start_time/rate) - search() returns PagedResult with total, page, total_pages - Case-insensitive recipient matching - Tests: each filter type, combined filters, sorting, pagination
- Add services/pool/ crate (paystream-pool) - build_pg_pool(): deadpool-postgres with configurable max_size, wait/create/recycle timeouts - build_redis_pool(): deadpool-redis with same PoolConfig - PoolConfig struct with sensible defaults (max=16, timeouts 5-10s) - pg_metrics() / redis_metrics() for monitoring pool size/available/waiting - Pools are lazy (no connection until first get()) — safe to build at startup - Unit tests for config and pool construction
feat: implement Redis caching layer
…ance-calculation-service feat: implement stream balance calculation service
…rage Implement Code Coverage Tracking
…-docs Write Database Schema Documentation
…ncellation-endpoint Create Stream Cancellation Endpoint
…recovery Implement Disaster Recovery Plan
…ats-service Build Stream Stats/Aggregation Service
…-forum Create Community Forum/Discussion Board
…ection Implement DDoS Protection
…-dashboard Add Analytics and Reporting Dashboard
…tion-sanitization Add Data Validation and Sanitization
…-tests Implement Integration Tests
…trics-monitoring Add Contract Metrics/Monitoring
Build E2E Test Suite
feat: set up Docker containerization (Vera3289#509)
feat: implement rate limiting in contract (Vera3289#506)
feat: implement event logging system (Vera3289#501)
feat: implement stream pause/resume (Vera3289#493)
…eckpoint feat: implement snapshot/checkpoint system (Vera3289#503)
…rollback feat: create deployment rollback strategy (Vera3289#513)
feat: create data migration system (Vera3289#505)
…culation feat: implement balance calculation logic (Vera3289#498)
…ates feat(templates): implement stream template system (Vera3289#596)
feat(streams): implement stream top-up endpoint (Vera3289#595)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes Vera3289#594
Full API key lifecycle: generation, validation, per-key rate limiting, rotation, revocation, and usage tracking — integrated into the existing auth middleware.
Changes
New files
api/services/apiKeyService.js— Core service: generatespsk_prefixed keys (32-byte CSPRNG), stores SHA-256 hashes (never raw keys), validates, enforces per-key sliding-window rate limits, supports rotation (revoke + re-issue) and revocation by id, tracks last-used timestamp and request countsapi/routes/apiKeys.js— REST interface for key management with swagger docsModified files
api/middleware/auth.js— X-API-Key path now goes throughapiKeyService.validateKey()+checkRateLimit(); returns 429 on rate limit breach; JWT path unchangedapi/server.js— Mounts/v1/api/api-keysrouterAPI Endpoints
POST/v1/api/api-keysGET/v1/api/api-keysPOST/v1/api/api-keys/:id/rotateDELETE/v1/api/api-keys/:idGET/v1/api/api-keys/:id/usageAcceptance Criteria
psk_prefix + 32-byte random, CSPRNGvalidateKey()windowMs+maxper keyrotateKey()— revokes old, creates new with same owner/namerevokeById()+DELETE /api-keys/:idlastUsedAttimestampauthMiddleware;ownerIdscopes listingSecurity notes