feat(exports): add GET /api/exports/health dependency probe - #1
Open
devcarole wants to merge 1184 commits into
Open
feat(exports): add GET /api/exports/health dependency probe#1devcarole wants to merge 1184 commits into
devcarole wants to merge 1184 commits into
Conversation
…en-rate-limit Feat/930 refresh token rate limit
…meout feat(forecast): add graceful timeout on /api/forecast (Closes CalloraOrg#935)
Add per-developer billing-concurrency stats admin endpoint (GrantFox FWC26). - Export sharedDeveloperSemaphore singleton from developerSemaphore.ts so the middleware and admin route share the same in-memory state - Add getActiveSlotCount(), isAtLimit(), and maxConcurrency getter to DeveloperSemaphore (mirrors KeySemaphore API) - Update createPerDevConcurrencyMiddleware to accept injectable semaphore and default to sharedDeveloperSemaphore when no options are customised - Add GET /api/admin/metrics/concurrency — snapshot of all developers with at least one in-flight billing request - Add GET /api/admin/metrics/concurrency/:developerId — live count and atLimit flag for a single developer - Mount new router at /metrics in the admin router - 27 focused tests, all passing; lint clean; zero TS errors in changed files - Add docs/per-dev-concurrency.md with API reference, config table, audit events, and operational notes Closes CalloraOrg#608
…ue-913 feat: add prometheus latency histogram for GET /api/maintenance
…ook-retry-override feat: add per-subscription webhook retry policy override
…lloraOrg#893) - Register apis_request_duration_seconds histogram in src/metrics/registry.ts with explicit buckets (0.001-10s) tuned for marketplace listing latencies and labels: route, method, status_code - Instrument all /api/apis handlers via middleware in src/routes/apis.ts to record request duration for ALL outcomes (success and error) - Implement recordApisLatency() helper function for direct recording - Add comprehensive test suite (src/__tests__/apisLatency.test.ts) covering: * Histogram registration and metadata * Direct recording with correct label values * Integration with route middleware * Error response capture (404, 4xx, 5xx) * Duration measurement accuracy (not hardcoded) - Document metric design, buckets, labels, and usage in docs/apis-latency-metric.md with PromQL examples and alerting guidelines Bucket rationale: Sub-millisecond granularity (1µs-50ms): cache hits + simple DB queries Tail visibility (100ms-10s): downstream service latency, slow clients Labels breakdown: route: /api/apis (constant) method: GET or POST (identifies request type) status_code: HTTP response status (enables error-path analysis) Closes CalloraOrg#893
CalloraOrg#896) Implement request deduplication for proxy POST/PATCH methods via the existing idempotencyMiddleware, enabling safe retries without risking duplicate upstream execution. CHANGES: - Applied idempotencyMiddleware to POST/PATCH routes in src/routes/proxyRoutes.ts - Explicit per-method routing (POST, PATCH, GET, DELETE, etc.) instead of catch-all - GET/DELETE bypass idempotency middleware (out of scope; naturally safe) - Idempotency-Key header is optional but recommended for safe retries FEATURES: - True request deduplication: repeated requests with same key/payload do NOT call upstream a second time; cached response is replayed instead - Payload mismatch detection: reusing a key with different payload returns 409 IDEMPOTENCY_KEY_REUSE_MISMATCH (prevents silent bugs) - Concurrent-duplicate handling: retries arriving while first is in-flight get 409 IDEMPOTENCY_IN_PROGRESS; upstream executes exactly once - Actor-scoped idempotency: different API keys cannot access each other's cached responses (prevents cross-tenant leaks) - PostgreSQL storage: safe for horizontal scaling; shared state across instances - 24-hour retention window: configurable, automatic TTL cleanup TESTS: - Added 20+ integration tests covering first request, replay, mismatch, in-progress, GET/DELETE bypass, actor scoping, canonicalization - All tests in src/__tests__/proxy.integration.test.ts DOCUMENTATION: - New: docs/api-proxy-idempotency.md (client-facing contract) - Header format, requirements, retention window - Response codes and behaviors (2xx, 409 scenarios) - Implementation examples (TypeScript retry loop) - Security and multi-tenancy notes - Troubleshooting guide - New: IDEMPOTENCY_KEY_PROXY_IMPLEMENTATION.md (internal design doc) - Architecture decisions, design rationale - Multi-instance safety verification - Concurrent-duplicate race handling - Questions for human review DEPLOYMENT: - No new dependencies required - No database migrations needed (idempotency_store table exists) - Uses existing IDEMPOTENCY_RETENTION_WINDOW_SECONDS env var - Backward compatible: Idempotency-Key is optional - Clients opt-in by including the header ISSUE: Closes CalloraOrg#896 (GrantFox FWC26 b#031) - Implements true request deduplication (no double downstream execution) - Handles concurrent retries correctly - Actor-scoped storage prevents cross-tenant data leaks - Multi-instance safe via PostgreSQL
Add SUBSCRIPTION_CORS_ALLOWED_ORIGINS env-driven CORS middleware to /api/subscriptions, matching the pattern established by the maintenance route CORS (MAINTENANCE_CORS_ALLOWED_ORIGINS). - createSubscriptionCorsMiddleware() in src/middleware/cors.ts — exact-match allowlist, deny by default, 10-min preflight cache - Applied as first middleware in createSubscriptionRouter() - SUBSCRIPTION_CORS_ALLOWED_ORIGINS added to env schema & .env.example - 5 new unit tests in cors.test.ts + Origin headers on all 56 existing subscription route tests closes#900
- Mount correlationMiddleware on the refresh-token router - Propagate X-Correlation-Id response header on every request - Replace getRequestId() with req.correlationId from the middleware - Add tests for correlation-id header propagation and structured logging Closes CalloraOrg#957
…nfrastructure including app factory, middleware, metrics, and routing modules.
- Extract exportsQuerySchema from inline route to src/validators/export.ts - Update src/routes/exports.ts to import from validator module - Add focused test suite in src/validators/export.test.ts (11 tests) Closes CalloraOrg#912
…age.openapi.test.ts
…-breaker-spike-884 feat(spike): add circuit breaker for audit service calls (closes CalloraOrg#884)
…loper-concurrency-stat-#608 feat: concurrency stat
…box-dispatcher feat(outbox): add partition-aware sharded dispatcher for high-volume …
…-keys-integration-test Feature/e2e api keys integration test
…gram-apis-latency Feat/prom histogram apis latency
…y-key-proxy Feat/idempotency key proxy
…port-security-headers feat: security header sweep for /api/exports CalloraOrg#885
…pike-examples docs: add openapi examples for spike route
…743-health-probe docs: Add /api/health/health dependency probe
…740-openapi-webhooks docs: Add OpenAPI examples for /api/webhooks
…subscriptions-histogram feat(metrics): add prometheus latency histogram for /api/subscription…
…738-proxy-test Feature/issue 738 proxy test
…735-etag-apis test: Add integration tests for ETag caching on /api/apis
- Pre-set strong ETag on GET /api/tenants from tenant data only,
so the tag is stable across requests that return the same list
regardless of volatile envelope fields (timestamp, requestId)
- Extend etagMiddleware to honour a pre-set ETag while still
evaluating If-None-Match via strong comparison (RFC 7232 §3.2),
preventing Express's built-in weak-comparison fresh module from
firing incorrectly on W/"..." tags
- Add focused ETag/304 tests to src/routes/tenants.test.ts:
- 200 with strong ETag header on first fetch
- 304 Not Modified when If-None-Match matches
- 200 when If-None-Match does not match
- 200 (not 304) for weak ETag — strong comparison only
- 401 for unauthenticated GET
- 500 propagation for repository errors
- Document GET /api/tenants caching behaviour in docs/tenants-api.md
Closes CalloraOrg#946
Apply CSP, X-Content-Type-Options, and Referrer-Policy to every /api/errors response via router.use(securityHeadersMiddleware). The middleware fires before all route handlers so even 401 and 400 error responses carry the headers. - src/routes/errors.ts: import securityHeadersMiddleware and mount it at the top of createErrorsRouter - src/routes/errors.test.ts: add focused security-header describe block covering GET /, GET /:id (404), POST (201/401/400), PATCH (200/404), PUT (200), DELETE (204/404) - docs/errors-security-headers.md: document the headers applied, rationale, implementation detail, and test coverage table Closes CalloraOrg#945
Add request/response examples for all webhook management endpoints:
- DELETE /api/webhooks/{developerId} (remove webhook)
- POST /api/webhooks/{developerId}/rotate-secret (rotate signing secret)
- PATCH /api/webhooks/{developerId}/retry-policy (update retry config)
- POST /api/webhooks/deliver/{developerId} (deliver webhook event)
Also adds 400 error response examples for POST /api/webhooks (missing
fields, invalid events, invalid URL, invalid retry policy).
Updates companion test to verify all new endpoint examples are present.
Closes CalloraOrg#871
Co-authored-by: Cursor <cursoragent@cursor.com>
…sage-validate feat: input validation usage
…red_json_access_logs feat: add structured JSON access logs for /api/forecast
feat: ETag/304 caching on GET /api/tenants (CalloraOrg#946)
…ers-errors-945 feat: security header sweep for /api/errors (CalloraOrg#945)
…ok-openapi-examples feat(openapi): add OpenAPI examples for /api/webhooks endpoints
…e-name Add graceful timeout on /api/plans [b#050]
Adds a public health probe endpoint at GET /api/subscriptions/health that reports the operational status of the subscriptions subsystem's external dependencies (database). The endpoint follows the same pattern as other subsystem health probes (e.g., /api/usage/health, /api/rate-limit/health): - Probes the database with a bounded timeout - Returns sanitised dependency status (ok/degraded/down) - Returns 503 when the database is down - Public (no auth required) for load-balancer health checks - Supports x-request-id correlation for structured logging Closes CalloraOrg#954 Co-authored-by: Cursor <cursoragent@cursor.com>
Adds a health probe for the /api/quotas route group, reporting the status
of its external dependencies (currently the shared PostgreSQL database,
which backs quota-request persistence and usage aggregation).
- src/routes/quotas/health.ts: GET / handler reusing the existing
checkDatabase/sanitizeCheck infrastructure from
src/services/healthCheck.ts and src/routes/health/dependencies.ts, so
the response shape ({ status, timestamp, dependencies }) and error
sanitization rules match the app's other dependency probes. Applies the
same correlationMiddleware and quotasDrainTracker used by
src/routes/quotas/counts.ts for structured logging and graceful
shutdown.
- src/routes/quotas.ts: mount the new router at /api/quotas/health,
after the shared per-user token-bucket rate limiter (same protection
as every other /api/quotas route).
- docs/quotas-health-probe.md + README.md: document the endpoint,
response shape, status codes, and correlation ID behavior.
- src/routes/quotas/health.test.ts: 8 tests covering healthy/down
database status, error sanitization, dependency key set, correlation
ID echo/generation, default pool wiring, and drain-tracker
compatibility (93% line coverage on the new route file).
Closes CalloraOrg#773
…alth-probe feat: add /api/quotas/health dependency probe
…-771-zod-forecast-validation feat(forecast): add Zod input validation for /api/forecast endpoints
…ions-health-probe feat(subscriptions): add /api/subscriptions/health dependency probe
…rg#728) - Implement health probe endpoint at GET /api/exports/health - Concurrently checks database, storage, queue, and notificationApi - Returns per-dependency status (ok/degraded/down) and aggregated overall - withTimeout() guard (5s) protects against hung probes - Structured JSON logging with correlation ID on every log line (x-correlation-id header or UUID v4 fallback) - ProbeRegistry DI pattern for easy test injection - 40 tests: all-healthy 200, partial/full failure 503, timeout 503, degraded 200, correlation ID echo/generation, log structure validation - health.ts coverage: 100% stmts, 100% funcs, 100% lines, 93.75% branches Build fixes (pre-existing issues resolved): - Rename jest.config.js -> jest.config.cjs (ESM package incompatibility) - Add tsconfig.test.json targeting CommonJS for Jest/ts-jest compatibility - Fix src/index.test.ts import extension (.js required for NodeNext) - Add isolatedModules: true to tsconfig.json - Upgrade ts-jest to 29.4.12 for Jest 30 support - Add --forceExit to test script
devcarole
pushed a commit
that referenced
this pull request
Jul 29, 2026
feat: add plugin marketplace API (CalloraOrg#469)
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.
Closes CalloraOrg#728