Skip to content

Feat/backend global validation pipe#461

Merged
ryzen-xp merged 6 commits into
Alien-Protocol:devfrom
KevinMB0220:feat/backend-global-validation-pipe
Apr 29, 2026
Merged

Feat/backend global validation pipe#461
ryzen-xp merged 6 commits into
Alien-Protocol:devfrom
KevinMB0220:feat/backend-global-validation-pipe

Conversation

@KevinMB0220
Copy link
Copy Markdown
Contributor

@KevinMB0220 KevinMB0220 commented Apr 28, 2026

Description

This PR addresses issue #441 by implementing a global validation pipe in the backend using NestJS's ValidationPipe. It ensures that all incoming HTTP request payloads are strictly validated against their Data Transfer Objects (DTOs), automatically stripping out unknown properties and rejecting requests with invalid data.

Closes #441

Changes Made

  • Global Validation Pipe: Enabled ValidationPipe globally in main.ts with whitelist: true, forbidNonWhitelisted: true, and transform: true.
  • Dependencies: Added class-validator and class-transformer to the project dependencies, and configured necessary testing tools (jest, supertest) in package.json.
  • DTO Decorators: Applied validation decorators (@IsString(), @IsNotEmpty(), @Matches(), @IsNumberString(), etc.) across multiple domains:
    • RegisterUsernameDto (Resolver Module)
    • PlaceBidDto (Auction Module)
    • AutoPayDto (Vault Module)
    • Created a new LoginDto (Auth Module)
  • Infrastructure Fixes: Added AppController and AppService to AppModule to resolve existing test failures.
  • Testing:
    • Added a new E2E test suite (validation.e2e-spec.ts) specifically to test the validation boundaries (e.g., rejecting invalid formats, missing properties, and extra properties).
    • Fixed ES module interop issues with supertest in existing E2E tests.

Acceptance Criteria Met

  • class-validator and class-transformer installed.
  • ValidationPipe globally applied with whitelist: true and forbidNonWhitelisted: true.
  • Validation decorators applied to Auth and Vault DTOs (as well as Resolver and Auction).
  • Invalid payloads correctly trigger a 400 Bad Request response.
  • npm run test (and npm run test:e2e) pass successfully.

How to Test

  1. Run npm install inside the backend/ directory.
  2. Start the development server with npm run start:dev.
  3. Attempt to send a POST request with invalid or extra payload properties to any implemented endpoint (e.g., /resolver/register with commitment: "invalid-hex" or an unlisted property).
  4. Verify that the server responds with a 400 Bad Request and an explicit error message detailing the validation failure.
  5. Alternatively, run npm run test:e2e in the backend/ directory to automatically verify validation rules.

Summary by CodeRabbit

  • New Features

    • Added a login request schema with validation and API docs.
  • Tests

    • Added end-to-end validation tests covering resolver registration and auction bid inputs.
  • Chores

    • Enabled global request validation across the backend.
    • Strengthened input validation for several API payloads (wallet addresses, amounts, usernames, autopay rules).
    • Expanded testing tooling and scripts.

@drips-wave
Copy link
Copy Markdown

drips-wave Bot commented Apr 28, 2026

@KevinMB0220 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

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 28, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 243162de-4441-4b40-ac82-347e2f51930f

📥 Commits

Reviewing files that changed from the base of the PR and between b2859f5 and 53c5a30.

📒 Files selected for processing (2)
  • backend/src/auction/dto/auction.dto.ts
  • backend/src/vault/dto/vault.dto.ts

📝 Walkthrough

Walkthrough

Adds class-validator/class-transformer and enables a global NestJS ValidationPipe; augments DTOs with validation decorators; registers AppController/AppService in AppModule; introduces Jest/Supertest test tooling and new e2e tests asserting 400 responses for invalid payloads.

Changes

Cohort / File(s) Summary
Package & Test infra
backend/package.json , backend/test/app.e2e-spec.ts, backend/test/validation.e2e-spec.ts
Adds Jest/ts-jest/supertest tooling and scripts; updates dev deps; adjusts supertest import and adds new validation e2e tests.
Application bootstrap & module
backend/src/main.ts, backend/src/app.module.ts
Enables global ValidationPipe (whitelist + forbidNonWhitelisted + transform) in main.ts; registers AppController and AppService in AppModule.
Auth & DTOs — validation
backend/src/auth/dto/login.dto.ts, backend/src/auction/dto/auction.dto.ts, backend/src/resolver/dto/resolver.dto.ts, backend/src/vault/dto/vault.dto.ts
Adds class-validator decorators (@IsNotEmpty, @Matches, @IsNumberString, @IsEnum, @IsBoolean) and Swagger metadata for auth DTOs and validation rules for auction/resolver/vault DTOs.

Sequence Diagram

sequenceDiagram
    participant Client
    participant NestApp as "NestJS App"
    participant ValPipe as "ValidationPipe"
    participant DTO as "DTO (class-validator)"
    participant Controller

    Client->>NestApp: POST /<endpoint> (payload)
    NestApp->>ValPipe: run global ValidationPipe
    ValPipe->>DTO: validate & transform payload
    alt valid
        DTO-->>ValPipe: valid
        ValPipe-->>Controller: forward transformed DTO
        Controller-->>Client: 200 OK / resource response
    else invalid
        DTO-->>ValPipe: validation errors
        ValPipe-->>Client: 400 Bad Request (validation details)
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • Alien-Protocol/Alien-Protocol#423 — touches same backend module, DTOs, and validation-related changes (overlapping files).
  • Alien-Protocol/Alien-Protocol#426 — adds global validation and testing/tooling changes similar to this PR.
  • Alien-Protocol/Alien-Protocol#420 — modifies AppModule metadata and backend configuration that overlaps with module edits here.

Suggested labels

Approved

Suggested reviewers

  • ryzen-xp

Poem

🐇 I hopped into code, nibbling bad payloads away,

DTOs neat and tidy now, no stray fields may stay.
Tests bounce the naughty ones with a firm little thump,
Validators guard the gates—hip hop, the build goes bump!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Feat/backend global validation pipe' clearly and directly summarizes the main change: adding global validation via a pipe in the backend.
Linked Issues check ✅ Passed All requirements from issue #441 are met: ValidationPipe enabled globally with whitelist/forbidNonWhitelisted, validation decorators added to auth/vault/resolver/auction DTOs, tests added, and implementation complete.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the global validation pipe: dependencies, DTOs, validation logic, tests, and supporting infrastructure (AppController/AppService) are all aligned with issue #441 requirements.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 0/1 reviews remaining, refill in 60 minutes.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (2)
backend/test/validation.e2e-spec.ts (1)

30-100: Use valid fixtures for the non-targeted fields.

These payloads reuse the same placeholder Stellar address everywhere, but that value does not satisfy the new regex. As a result, each request can raise unrelated validation errors and make the assertions less precise. A valid address fixture would make the suite more stable.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/test/validation.e2e-spec.ts` around lines 30 - 100, Tests reuse an
invalid placeholder Stellar address which triggers unrelated validation
failures; introduce a single valid fixture (e.g., VALID_STELLAR_ADDRESS) that
matches the Stellar address regex and replace every hard-coded
'GABC1234STELLAR...' occurrence in the register and auction tests (the POST to
'/resolver/register' and '/auction/1/bid' cases) with that fixture so
non-targeted fields pass validation and assertions become precise; add the
constant near the top of validation.e2e-spec.ts and use it in the test payloads
for username/walletAddress fields.
backend/src/vault/dto/vault.dto.ts (1)

32-55: Move these validators to a request DTO if you expect them to run.

AutoPayDto is only used as a GET response today, so these decorators never execute on the current route surface. A dedicated input DTO would make the validation intent explicit.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/src/vault/dto/vault.dto.ts` around lines 32 - 55, AutoPayDto
currently contains validation decorators but is only used as a GET/response DTO
so validators never run; extract the input-specific validators into a new
request DTO (e.g., CreateAutoPayDto and/or UpdateAutoPayDto) containing the
decorated properties (id, recipient, amount, interval, active) and leave
AutoPayDto as a plain response DTO (or rename to AutoPayResponseDto); update the
controller methods that accept POST/PUT/PATCH payloads to use the new request
DTO(s) instead of AutoPayDto so class-validator runs, and keep any ApiProperty
metadata in both request and response DTOs as needed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@backend/package.json`:
- Line 13: The npm script "test:debug" in package.json preloads "-r
find-node-modules" which is not declared, causing MODULE_NOT_FOUND; either add
"find-node-modules" to devDependencies (so npm install will provide it) or
remove the "-r find-node-modules" preload from the "test:debug" script; update
package.json accordingly and run npm install to verify the script runs (refer to
the "test:debug" script entry in package.json to locate the change).

In `@backend/src/auction/dto/auction.dto.ts`:
- Around line 31-36: The Swagger ApiProperty example for the bidder field does
not match the Stellar address regex used by the `@Matches` validator; update the
example in the ApiProperty for the bidder property so it is a valid 56-character
Stellar public key (starts with 'G' and uses only A-Z and 2-7) to satisfy the
regex in the Matches decorator (referenced symbol: bidder, decorators:
`@ApiProperty` and `@Matches`(/^G[A-Z2-7]{55}$/)).

In `@backend/src/auth/dto/login.dto.ts`:
- Around line 5-11: The Swagger example for the address field conflicts with its
validator: update the ApiProperty example on the address property so it
satisfies the Matches(/^G[A-Z2-7]{55}$/) constraint — provide a 56-character
string that starts with 'G' and contains only A–Z and digits 2–7 (i.e., change
the example in the ApiProperty decorator for the address field to a value
matching the regex).

In `@backend/src/resolver/dto/resolver.dto.ts`:
- Around line 16-37: Update the ApiProperty examples to match the new validation
regexes: replace the walletAddress example with a valid 56-char Stellar public
key starting with 'G' and containing only A-Z and 2-7 (e.g. a 56-character
string like "G" + 55 valid base32 chars) in the walletAddress property, and
replace the commitment example with a 32-byte hex string prefixed by 0x (64 hex
chars after 0x) for the commitment property so they pass the
`@Matches`(/^G[A-Z2-7]{55}$/) and `@Matches`(/^0x[a-fA-F0-9]{64}$/) validators
respectively; ensure the username example remains valid for
`@Matches`(/^[a-zA-Z0-9_]{3,20}$/).

---

Nitpick comments:
In `@backend/src/vault/dto/vault.dto.ts`:
- Around line 32-55: AutoPayDto currently contains validation decorators but is
only used as a GET/response DTO so validators never run; extract the
input-specific validators into a new request DTO (e.g., CreateAutoPayDto and/or
UpdateAutoPayDto) containing the decorated properties (id, recipient, amount,
interval, active) and leave AutoPayDto as a plain response DTO (or rename to
AutoPayResponseDto); update the controller methods that accept POST/PUT/PATCH
payloads to use the new request DTO(s) instead of AutoPayDto so class-validator
runs, and keep any ApiProperty metadata in both request and response DTOs as
needed.

In `@backend/test/validation.e2e-spec.ts`:
- Around line 30-100: Tests reuse an invalid placeholder Stellar address which
triggers unrelated validation failures; introduce a single valid fixture (e.g.,
VALID_STELLAR_ADDRESS) that matches the Stellar address regex and replace every
hard-coded 'GABC1234STELLAR...' occurrence in the register and auction tests
(the POST to '/resolver/register' and '/auction/1/bid' cases) with that fixture
so non-targeted fields pass validation and assertions become precise; add the
constant near the top of validation.e2e-spec.ts and use it in the test payloads
for username/walletAddress fields.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e779f3ec-ca5e-4074-9fe9-f78a8ed9a77e

📥 Commits

Reviewing files that changed from the base of the PR and between 8b75f9b and b2859f5.

⛔ Files ignored due to path filters (1)
  • backend/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (9)
  • backend/package.json
  • backend/src/app.module.ts
  • backend/src/auction/dto/auction.dto.ts
  • backend/src/auth/dto/login.dto.ts
  • backend/src/main.ts
  • backend/src/resolver/dto/resolver.dto.ts
  • backend/src/vault/dto/vault.dto.ts
  • backend/test/app.e2e-spec.ts
  • backend/test/validation.e2e-spec.ts

Comment thread backend/package.json
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r find-node-modules node_modules/.bin/jest --runInBand",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

node - <<'NODE'
const fs = require('fs');
const pkg = JSON.parse(fs.readFileSync('backend/package.json', 'utf8'));
console.log('declared:', pkg.dependencies?.['find-node-modules'] ?? pkg.devDependencies?.['find-node-modules'] ?? 'missing');
NODE

rg -n '"find-node-modules"' backend/package-lock.json backend/pnpm-lock.yaml backend/yarn.lock 2>/dev/null || true
node -e "require.resolve('find-node-modules'); console.log('resolves')"

Repository: Alien-Protocol/Alien-Protocol

Length of output: 906


Add find-node-modules to devDependencies or remove it from the test:debug preload.

The test:debug script preloads -r find-node-modules, but this package is not declared in the manifest and cannot be resolved. On a clean install, npm run test:debug will fail with MODULE_NOT_FOUND.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/package.json` at line 13, The npm script "test:debug" in package.json
preloads "-r find-node-modules" which is not declared, causing MODULE_NOT_FOUND;
either add "find-node-modules" to devDependencies (so npm install will provide
it) or remove the "-r find-node-modules" preload from the "test:debug" script;
update package.json accordingly and run npm install to verify the script runs
(refer to the "test:debug" script entry in package.json to locate the change).

Comment on lines 31 to 36
@ApiProperty({ description: 'Bidder Stellar address', example: 'GXYZ9876STELLAR1234BIDDERADDRESS' })
@IsNotEmpty()
@Matches(/^G[A-Z2-7]{55}$/, {
message: 'Invalid Stellar wallet address format',
})
bidder: string;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Keep the bid example consistent with the Stellar regex.

bidder's example also fails ^G[A-Z2-7]{55}$, so Swagger is advertising an invalid sample payload here as well.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/src/auction/dto/auction.dto.ts` around lines 31 - 36, The Swagger
ApiProperty example for the bidder field does not match the Stellar address
regex used by the `@Matches` validator; update the example in the ApiProperty for
the bidder property so it is a valid 56-character Stellar public key (starts
with 'G' and uses only A-Z and 2-7) to satisfy the regex in the Matches
decorator (referenced symbol: bidder, decorators: `@ApiProperty` and
`@Matches`(/^G[A-Z2-7]{55}$/)).

Comment on lines +5 to +11
@ApiProperty({ description: 'Stellar wallet address', example: 'GABC1234STELLAR5678WALLETADDRESS' })
@IsString()
@IsNotEmpty()
@Matches(/^G[A-Z2-7]{55}$/, {
message: 'Invalid Stellar wallet address format',
})
address: string;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Use a Swagger example that satisfies the validator.

GABC1234STELLAR5678WALLETADDRESS does not match ^G[A-Z2-7]{55}$, so the documented sample request is self-contradictory and will fail if copied into a client.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/src/auth/dto/login.dto.ts` around lines 5 - 11, The Swagger example
for the address field conflicts with its validator: update the ApiProperty
example on the address property so it satisfies the Matches(/^G[A-Z2-7]{55}$/)
constraint — provide a 56-character string that starts with 'G' and contains
only A–Z and digits 2–7 (i.e., change the example in the ApiProperty decorator
for the address field to a value matching the regex).

Comment on lines 16 to +37
@ApiProperty({ description: 'Username to register (without @)', example: 'alice' })
@IsString()
@IsNotEmpty()
@Matches(/^[a-zA-Z0-9_]{3,20}$/, {
message: 'Username must be 3-20 characters long and contain only letters, numbers, and underscores',
})
username: string;

@ApiProperty({ description: 'Stellar wallet address to link', example: 'GABC1234STELLAR5678WALLETADDRESS' })
@IsString()
@IsNotEmpty()
@Matches(/^G[A-Z2-7]{55}$/, {
message: 'Invalid Stellar wallet address format',
})
walletAddress: string;

@ApiProperty({ description: 'Zero-knowledge commitment hash', example: '0xabc123...' })
@IsString()
@IsNotEmpty()
@Matches(/^0x[a-fA-F0-9]{64}$/, {
message: 'Commitment must be a 32-byte hex string prefixed with 0x',
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Align the Swagger examples with the new validation rules.

The current walletAddress and commitment examples do not satisfy the regex constraints added below, so the generated docs will mislead API consumers and produce copy-paste payloads that fail validation.

💡 Suggested update
   `@ApiProperty`({ description: 'Stellar wallet address to link', example: 'GABC1234STELLAR5678WALLETADDRESS' })
+  `@ApiProperty`({
+    description: 'Stellar wallet address to link',
+    example: `G${'A'.repeat(55)}`,
+  })
@@
-  `@ApiProperty`({ description: 'Zero-knowledge commitment hash', example: '0xabc123...' })
+  `@ApiProperty`({
+    description: 'Zero-knowledge commitment hash',
+    example: `0x${'a'.repeat(64)}`,
+  })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/src/resolver/dto/resolver.dto.ts` around lines 16 - 37, Update the
ApiProperty examples to match the new validation regexes: replace the
walletAddress example with a valid 56-char Stellar public key starting with 'G'
and containing only A-Z and 2-7 (e.g. a 56-character string like "G" + 55 valid
base32 chars) in the walletAddress property, and replace the commitment example
with a 32-byte hex string prefixed by 0x (64 hex chars after 0x) for the
commitment property so they pass the `@Matches`(/^G[A-Z2-7]{55}$/) and
`@Matches`(/^0x[a-fA-F0-9]{64}$/) validators respectively; ensure the username
example remains valid for `@Matches`(/^[a-zA-Z0-9_]{3,20}$/).

@ryzen-xp ryzen-xp self-requested a review April 29, 2026 03:00
@ryzen-xp ryzen-xp added the APPROVED This PR is ready for merging . label Apr 29, 2026
@ryzen-xp ryzen-xp merged commit 3ab816d into Alien-Protocol:dev Apr 29, 2026
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

APPROVED This PR is ready for merging .

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: add input validation pipe globally to backend

2 participants