Skip to content

feat(docs): complete the OpenAPI documentation and harden the agent rate limits - #459

Merged
Cjay-Cyber-2 merged 2 commits into
ASTROIDX556:mainfrom
billcode124:feat/448-swagger-443-rate-limit
Oct 21, 2026
Merged

Cjay-Cyber-2 merged 2 commits into
ASTROIDX556:mainfrom
billcode124:feat/448-swagger-443-rate-limit

Conversation

@billcode124

Copy link
Copy Markdown
Contributor

Summary

Completes the OpenAPI/Swagger documentation across every domain module and hardens the Redis-backed rate limiting of the agent-facing endpoints.

Closes #448
Closes #443

Type of change

  • Bug fix
  • New feature
  • Refactor / cleanup
  • Documentation
  • CI / tooling

Why

#448 — Swagger documentation. The generated document described the status of most endpoints but not their shape: the success schema was systematically dropped and the error responses had no body at all, so the document could not be used to generate a client.

The success schema was lost for two reasons, both inside the shared decorators:

  • @ApiEnvelope always wrote a 200 response while the route documented its own status (201 for creations), so the envelope landed on a status the endpoint never answers with;
  • @ApiPaginationQuery replaced the response of the list endpoints instead of adding the X-Total-Count header to it, wiping the envelope schema of every list route.

Both decorators now compose:

  • @ApiEnvelope(model, { isArray, status, description, headers }) owns the success response (status, description and schema) and is the only decorator that may describe it;
  • @ApiPaginatedEnvelope(model) documents a list response together with its total-count header;
  • @ApiPaginationQuery() documents only the query parameters;
  • the new @ApiErrorResponses({ validation, unauthorized, forbidden, notFound, conflict, unprocessable, tooManyRequests, serverError }) references a shared ApiErrorEnvelopeDto — the RFC 9457 problem-details body every error returns — instead of repeating an empty response per status code. A string instead of true overrides the default description.

With that in place every endpoint of the 21 domain modules documents its success schema, its request body and the error statuses it can answer with; 34 response DTOs were added where the module had none, and every property of every schema now carries a description (and an example where it helps).

src/openapi.spec.ts grew from a smoke test into a documentation check: every operation needs a tag, a summary, a documented success schema and error responses, every $ref has to resolve to a schema that exists (no missing type definitions) and every schema property has to be documented. It runs as npm run docs:check and as a dedicated CI step.

#443 — agent transaction rate limiting. The Redis sliding-window limiter that guards transaction submission bucketed by organization, so one noisy agent could exhaust the budget of every other agent of the same organization.

  • The window is now bucketed per acting agent (route parameter, body, query or x-agent-id header) first, then per API key, per organization and finally per IP. The identity resolution moved into a shared helper (resolve-agent-id) used by both limiters, so the two cannot drift apart again.
  • The agent command routes (pause, resume, suspend, wallet assignment) are rate limited as well.
  • Retry-After was always 1 second: it was derived from the window start instead of the oldest request in the window. The oldest member is now read in the same atomic MULTI/EXEC transaction, so the header points at the moment the next request is accepted.
  • The global limiter still caps the total traffic per API key and per user, so the per-agent bucket does not weaken the overall protection.

Testing

  • src/common/guards/sliding-window-throttler.guard.spec.ts — normal requests, limit violations, the HTTP 429 status, the Retry-After value, per-agent bucketing and concurrent requests (a fake Redis with an atomic MULTI/EXEC proves that exactly limit requests of a burst are accepted).
  • src/modules/agents/tests/agent-rate-limiter.spec.ts — the per-agent limiter, including concurrent requests and per-agent windows.
  • src/openapi.spec.ts — the documentation validity check (8 tests).

Checklist

  • npm run build passes
  • npm test passes
  • npm run lint passes
  • npm run typecheck passes
  • npm run docs:check passes
  • npm run db:verify passes (no schema change in this PR)
  • No secrets added to tracked files
  • PR description explains the why, not just the what

…ate limits

Closes ASTROIDX556#448
Closes ASTROIDX556#443

Swagger documentation (ASTROIDX556#448)

The OpenAPI document only described the success status of most endpoints:
the response schema was systematically dropped and the error responses had no
body, so the document could not be used to generate a client.

- The success schema was lost because @ApiEnvelope always wrote a 200 response
  while the route documented its own status, and @ApiPaginationQuery replaced
  the response of the list endpoints instead of adding the X-Total-Count
  header to it. Both decorators now compose: @ApiEnvelope takes the status,
  the description and the response headers, @ApiPaginatedEnvelope documents a
  list response with its total-count header, and @ApiPaginationQuery only
  documents the query parameters.
- New @ApiErrorResponses decorator references a shared ApiErrorEnvelopeDto
  (the RFC 9457 problem-details body every error returns) instead of
  repeating an empty response per status code.
- Every endpoint of the 21 domain modules now documents its success schema,
  its request body and the error statuses it can answer with; 34 response DTOs
  were added where none existed.
- Every property of every schema carries a description and, where it helps,
  an example.
- src/openapi.spec.ts grew from a smoke test into a documentation check: every
  operation needs a tag, a summary, a documented success schema and error
  responses, every $ref has to resolve and every schema property has to be
  documented. It runs as `npm run docs:check` and as a CI step.

Agent transaction rate limiting (ASTROIDX556#443)

- The sliding-window limiter that guards transaction submission now buckets
  per acting agent (route parameter, body, query or x-agent-id header) before
  the API key, the organization and the IP, so one agent can no longer
  exhaust the budget of the other agents of the same organization. The agent
  identity resolution moved into a shared helper used by both limiters.
- The agent command routes (pause, resume, suspend, wallet assignment) are
  rate limited as well.
- Retry-After was always 1 second because it was derived from the window
  start. The oldest member of the window is now read in the same atomic
  transaction, so the header points at the moment the next request is
  accepted.
- Tests cover normal requests, limit violations, the Retry-After value,
  per-agent bucketing and concurrent requests (the window is applied in a
  MULTI/EXEC transaction, so exactly `limit` requests of a burst are
  accepted).
@drips-wave

drips-wave Bot commented Oct 21, 2026

Copy link
Copy Markdown

@billcode124 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Cjay-Cyber-2
Cjay-Cyber-2 merged commit 571a451 into ASTROIDX556:main Oct 21, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Swagger API Documentation Decorators across All Controller Modules Add Rate Limiting Guard for Agent Transaction Submission Endpoints

2 participants