Some checks failed
CI / Lint → Typecheck → Test → Build (22) (push) Failing after 12s
CI / E2E Tests (push) Has been skipped
CodeQL Analysis / CodeQL (javascript-typescript) (push) Failing after 53s
Deploy / Build API Image (push) Failing after 22s
Deploy / Build Web Image (push) Failing after 14s
Deploy / Build AI Services Image (push) Failing after 12s
E2E Tests / Playwright E2E (push) Failing after 9s
Security Scanning / Dependency Audit (pnpm) (push) Failing after 2s
Security Scanning / Trivy Scan — API Image (push) Failing after 50s
Security Scanning / Trivy Scan — Web Image (push) Failing after 38s
Deploy / Deploy to Staging (push) Has been skipped
Deploy / Smoke Test Staging (push) Has been skipped
Deploy / Smoke Test Production (push) Has been skipped
Deploy / Deploy to Production (push) Has been skipped
Security Scanning / Trivy Scan — AI Services Image (push) Failing after 36s
Security Scanning / Trivy Filesystem Scan (push) Failing after 33s
Security Scanning / Security Gate (push) Failing after 1s
Deploy / Rollback Staging (push) Has been skipped
Deploy / Rollback Production (push) Has been skipped
Closes four gaps the Swagger audit flagged as blocking a full MVP demo,
plus a general documentation pass.
P0 — Forgot/Reset password (auth)
- POST /auth/forgot-password (anti-enumeration: always 200)
- POST /auth/reset-password
- Reuses the Redis-OTP pattern from email/phone change; new key prefix
auth:password_reset_otp with 15-min TTL.
- Emits PasswordResetRequestedEvent; new listener in notifications
dispatches the existing password.reset email template (otp +
expiryMinutes variables already in template.service.ts).
- UserEntity gains changePassword(HashedPassword) domain method; reset
also revokes all refresh tokens for the user.
P0 — Favorites module
- New SavedListing Prisma model (unique(userId, listingId)) with User
and Listing back-relations; schema pushed via db push since the
remote DB was out of sync with migration history.
- New apps/api/src/modules/favorites/ module following the reviews
module's shape (DDD/CQRS: domain repo + Prisma impl + 2 commands
+ 2 queries + controller).
- POST /favorites/:listingId, DELETE /favorites/:listingId,
GET /favorites (paginated), GET /favorites/:listingId/check. All
guarded by JwtAuthGuard.
- FavoritesModule wired into AppModule.
P1 — Resend OTP (auth)
- POST /auth/resend-otp for EMAIL_CHANGE | PHONE_CHANGE. Reads the
pending OTP payload out of Redis and re-emits the original event
without minting a new code, so TTL semantics stay intact. Password
reset resend is done by re-POSTing /auth/forgot-password and is
deliberately not in this enum.
P1 — Agent self-upgrade (agents)
- POST /agents/me/upgrade lets a BUYER/SELLER convert to AGENT. Creates
an Agent row (isVerified=false) and flips User.role in one
$transaction. Rejects if already AGENT/ADMIN or if an Agent row
already exists.
P2 — Swagger enrichment
- @ApiConsumes('multipart/form-data') + body schema on listings media
upload.
- GET /subscriptions/quota/:metric now enumerates the real metric
values from METRIC_TO_PLAN_FIELD.
- POST /avm/batch and /analytics/valuation/batch document the max=50
batch size from their DTO's @ArrayMaxSize.
- GET /admin/dashboard gains a realistic response example schema.
- Admin-gated endpoints in projects/transfer/industrial gain concrete
400/401/403/404 responses.
Swagger endpoint count: 170 → 178. Typecheck clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
25 lines
1.2 KiB
TypeScript
25 lines
1.2 KiB
TypeScript
import { Module } from '@nestjs/common';
|
|
import { CqrsModule } from '@nestjs/cqrs';
|
|
import { AddFavoriteHandler } from './application/commands/add-favorite/add-favorite.handler';
|
|
import { RemoveFavoriteHandler } from './application/commands/remove-favorite/remove-favorite.handler';
|
|
import { IsFavoritedHandler } from './application/queries/is-favorited/is-favorited.handler';
|
|
import { ListFavoritesHandler } from './application/queries/list-favorites/list-favorites.handler';
|
|
import { SAVED_LISTING_REPOSITORY } from './domain/repositories/saved-listing.repository';
|
|
import { PrismaSavedListingRepository } from './infrastructure/repositories/prisma-saved-listing.repository';
|
|
import { FavoritesController } from './presentation/controllers/favorites.controller';
|
|
|
|
const CommandHandlers = [AddFavoriteHandler, RemoveFavoriteHandler];
|
|
const QueryHandlers = [ListFavoritesHandler, IsFavoritedHandler];
|
|
|
|
@Module({
|
|
imports: [CqrsModule],
|
|
controllers: [FavoritesController],
|
|
providers: [
|
|
{ provide: SAVED_LISTING_REPOSITORY, useClass: PrismaSavedListingRepository },
|
|
...CommandHandlers,
|
|
...QueryHandlers,
|
|
],
|
|
exports: [SAVED_LISTING_REPOSITORY],
|
|
})
|
|
export class FavoritesModule {}
|