Skip to content

feat(audit): structured audit interceptor on the internal event bus - #478

Merged
Cjay-Cyber-2 merged 1 commit into
ASTROIDX556:mainfrom
khaylebfortune:implement-structured-audit
Oct 22, 2026
Merged

Cjay-Cyber-2 merged 1 commit into
ASTROIDX556:mainfrom
khaylebfortune:implement-structured-audit

Conversation

@khaylebfortune

@khaylebfortune khaylebfortune commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Closes #402
Closes #403
Closes #404
Closes #405

#405 — Structured audit log interceptor

  • New StructuredAuditInterceptor audits only the routes marked with @AuditAction() and publishes an audit.recorded event on the internal event bus (EventBusService -> @nestjs/event-emitter). The publication is never awaited, so the response cycle is not blocked by the audit write.
  • The event captures the request metadata (method, path, sanitized body, params, query), the authenticated user id, the acting agent id, the client IP and user agent, the timestamp, the response status code and the handler duration. Payloads pass through the shared audit sanitizer, so private keys, secrets, API keys, bearer tokens and JWTs are redacted before the record is built.
  • @AuditAction() now also accepts { action, entity, description }; normalizeAuditAction() resolves both the string and the object form.
  • New AuditRecordedListener turns the event into the hash-chained audit-log row and swallows (but logs) persistence failures.
  • AuditInterceptor and AuditLogInterceptor skip the routes owned by the structured path, so every audited operation leaves exactly one row.

#402 — Zod-validated agent identity module

  • The agent schemas are strict, trim and bound the display name, capabilities and metadata, and reject duplicated capabilities.
  • A new optional publicKey is validated against the Stellar strkey checksum and persisted as agent metadata.
  • Duplicate agent handles are rejected with a 409 CONFLICT before the Prisma repository is touched.
  • New controller spec asserts the standardized RFC 9457 error envelope for invalid payloads over real HTTP.

#403 — Retry and dead-letter handling for the transaction worker

  • The transaction queue is registered with an explicit retry ceiling (5) and an exponential backoff base (2s).
  • runWorkerJob exposes an onFailure hook with the failure classification.
  • The transaction worker warns on a retryable failure and emits a dead_letter.job_failed domain event when the retries are exhausted, so a permanently failed transaction is visible in the event ledger next to the dead-letter queue entry.

#404 — Enhanced spending policy rule evaluator

  • New velocity rule capping the number of transactions per rolling window, with per-window counters resolved by the repository.
  • New multi-condition rules groups with AND/OR logic, seven comparable fields and eight operators.
  • Time windows are now evaluated in an optional IANA time zone.
  • New engine, repository and service tests cover the pass, fail and edge cases of every new rule.

Closes ASTROIDX556#402, closes ASTROIDX556#403, closes ASTROIDX556#404, closes ASTROIDX556#405

ASTROIDX556#405 — Structured audit log interceptor
- New `StructuredAuditInterceptor` audits only the routes marked with
  `@AuditAction()` and publishes an `audit.recorded` event on the internal
  event bus (`EventBusService` -> `@nestjs/event-emitter`). The publication
  is never awaited, so the response cycle is not blocked by the audit write.
- The event captures the request metadata (method, path, sanitized body,
  params, query), the authenticated user id, the acting agent id, the client
  IP and user agent, the timestamp, the response status code and the handler
  duration. Payloads pass through the shared audit sanitizer, so private
  keys, secrets, API keys, bearer tokens and JWTs are redacted before the
  record is built.
- `@AuditAction()` now also accepts `{ action, entity, description }`;
  `normalizeAuditAction()` resolves both the string and the object form.
- New `AuditRecordedListener` turns the event into the hash-chained audit-log
  row and swallows (but logs) persistence failures.
- `AuditInterceptor` and `AuditLogInterceptor` skip the routes owned by the
  structured path, so every audited operation leaves exactly one row.

ASTROIDX556#402 — Zod-validated agent identity module
- The agent schemas are strict, trim and bound the display name, capabilities
  and metadata, and reject duplicated capabilities.
- A new optional `publicKey` is validated against the Stellar strkey checksum
  and persisted as agent metadata.
- Duplicate agent handles are rejected with a `409 CONFLICT` before the
  Prisma repository is touched.
- New controller spec asserts the standardized RFC 9457 error envelope for
  invalid payloads over real HTTP.

ASTROIDX556#403 — Retry and dead-letter handling for the transaction worker
- The transaction queue is registered with an explicit retry ceiling (5) and
  an exponential backoff base (2s).
- `runWorkerJob` exposes an `onFailure` hook with the failure classification.
- The transaction worker warns on a retryable failure and emits a
  `dead_letter.job_failed` domain event when the retries are exhausted, so a
  permanently failed transaction is visible in the event ledger next to the
  dead-letter queue entry.

ASTROIDX556#404 — Enhanced spending policy rule evaluator
- New `velocity` rule capping the number of transactions per rolling window,
  with per-window counters resolved by the repository.
- New multi-condition `rules` groups with `AND`/`OR` logic, seven
  comparable fields and eight operators.
- Time windows are now evaluated in an optional IANA time zone.
- New engine, repository and service tests cover the pass, fail and edge
  cases of every new rule.
@Cjay-Cyber-2
Cjay-Cyber-2 merged commit d082ad5 into ASTROIDX556:main Oct 22, 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

2 participants