{"id":37454827,"url":"https://github.com/viniciusferreira7/fast-feet-api","last_synced_at":"2026-04-16T20:04:47.781Z","repository":{"id":329431582,"uuid":"1115169826","full_name":"viniciusferreira7/fast-feet-api","owner":"viniciusferreira7","description":"API built for the fictional delivery company FastFeet, managing the full order lifecycle with features like admin/courier permissions, order tracking, and photo-based delivery confirmation. A reference UI layout is provided to illustrate how the endpoints are consumed.","archived":false,"fork":false,"pushed_at":"2026-04-10T13:56:15.000Z","size":5233,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-10T15:28:48.449Z","etag":null,"topics":["ci-cd","clean-architecture","ddd","docker","e2e-tests","nestjs","openai","typescript","unit-testing"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/viniciusferreira7.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-12T12:51:48.000Z","updated_at":"2026-04-10T13:56:18.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/viniciusferreira7/fast-feet-api","commit_stats":null,"previous_names":["viniciusferreira7/fast-feet-api"],"tags_count":35,"template":false,"template_full_name":null,"purl":"pkg:github/viniciusferreira7/fast-feet-api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/viniciusferreira7%2Ffast-feet-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/viniciusferreira7%2Ffast-feet-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/viniciusferreira7%2Ffast-feet-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/viniciusferreira7%2Ffast-feet-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/viniciusferreira7","download_url":"https://codeload.github.com/viniciusferreira7/fast-feet-api/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/viniciusferreira7%2Ffast-feet-api/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31902128,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-16T18:22:33.417Z","status":"ssl_error","status_checked_at":"2026-04-16T18:21:47.142Z","response_time":69,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ci-cd","clean-architecture","ddd","docker","e2e-tests","nestjs","openai","typescript","unit-testing"],"created_at":"2026-01-16T06:59:39.491Z","updated_at":"2026-04-16T20:04:47.773Z","avatar_url":"https://github.com/viniciusferreira7.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 📦 FastFeet API\n\n\u003e ⚠️ **Work In Progress** - This project is currently under active development.\n\nA robust package delivery management system built with NestJS, following Domain-Driven Design (DDD) and Clean Architecture principles.\n\n## 📋 Overview\n\nFastFeet API is a backend application for managing package deliveries, supporting two types of users: delivery persons and administrators. The system handles the complete delivery lifecycle from package creation to final delivery or return.\n\nFor detailed requirements and features, see [REQUIREMENTS.md](./REQUIREMENTS.md).\n\n## 🛠️ Tech Stack\n\n- **Framework**: [NestJS](https://nestjs.com/) v11\n- **Runtime**: Node.js 20\n- **Package Manager**: pnpm v10.25.0\n- **HTTP Server**: Fastify\n- **Language**: TypeScript\n- **ORM**: Drizzle ORM (PostgreSQL)\n- **Password Hashing**: Argon2 (via argon2 package)\n- **Email**: Resend API\n- **File Storage**: Cloudflare R2 (S3-compatible)\n- **Observability**: OpenTelemetry (traces, metrics, logs via OTLP)\n- **Schema Validation**: Zod (environment variables)\n- **Code Quality**: Biome (linting \u0026 formatting)\n- **Testing**: Vitest\n- **Containerization**: Docker (multi-arch support)\n- **CI/CD**: GitHub Actions\n- **Semantic Release**: Automated versioning and changelog\n\n## 🚀 Getting Started\n\n### Prerequisites\n\n- Node.js 20 or higher\n- pnpm 10.25.0 or higher\n- Docker and Docker Compose (for local database)\n\n### Installation\n\n```bash\n# Install dependencies\npnpm install\n\n# Start PostgreSQL database\npnpm run prestart:dev\n\n# Start development server\npnpm run start:dev\n```\n\n## 📜 Available Scripts\n\n```bash\n# Development\npnpm run start:dev          # Start in watch mode\npnpm run start:debug        # Start with debugger\npnpm run prestart:dev       # Start PostgreSQL database\n\n# Build\npnpm run build              # Build the application\n\n# Production\npnpm run start:prod         # Run production build\n\n# Docker\npnpm run docker:build       # Build Docker image with git commit tag\npnpm run docker:build:prod  # Build production Docker image\n\n# Code Quality\npnpm run check              # Run Biome checks\npnpm run check:fix          # Fix Biome issues automatically\npnpm run lint               # Run Biome linter\npnpm run format             # Format code with Biome\npnpm run check:type         # TypeScript type checking\npnpm run verify             # Pull, test, format, and type-check (pre-commit)\n\n# Testing\npnpm run test               # Run unit tests\npnpm run test:watch         # Run tests in watch mode\npnpm run test:cov           # Run tests with coverage\npnpm run test:debug         # Run tests with debugger\npnpm run test:e2e           # Run E2E tests\npnpm run test:e2e:watch     # Run E2E tests in watch mode\n```\n\n## 🐳 Docker\n\n### Build\n\n```bash\n# Build production image\ndocker build -t fast-feet-api:latest .\n\n# Build for specific architecture\ndocker build --platform linux/amd64 -t fast-feet-api:amd64 .\ndocker build --platform linux/arm64 -t fast-feet-api:arm64 .\n```\n\n### Run\n\n```bash\n# Run container\ndocker run -p 3333:3333 fast-feet-api:latest\n```\n\nThe application will be available at `http://localhost:3333`.\n\n## 🏗️ Architecture\n\nThe project follows:\n\n- **Domain-Driven Design (DDD)**: Organized around business domains\n- **Clean Architecture**: Separation of concerns with clear boundaries\n- **Domain Events**: Event-driven communication between aggregates\n- **RBAC**: Role-Based Access Control for authorization\n\n### Project Structure\n\n```\nsrc/\n├── core/                           # Core building blocks\n│   ├── entities/                   # Base entity and aggregate root classes\n│   │   ├── aggregate-root.ts      # Base class for aggregates\n│   │   ├── entity.ts              # Base entity class\n│   │   └── value-object/          # Value object base classes\n│   │       ├── pagination.ts      # Pagination value object\n│   │       ├── unique-entity-id.ts\n│   │       └── value-object.ts\n│   ├── events/                     # Domain events infrastructure\n│   │   ├── domain-event.ts        # Domain event interface\n│   │   ├── domain-events.ts       # Domain events dispatcher\n│   │   └── event-handler.ts       # Event handler interface\n│   ├── repositories/               # Core repository abstractions\n│   │   └── pagination-params.ts\n│   ├── watched-list.ts            # Watched list for tracking collection changes\n│   ├── either.ts                  # Either monad for functional error handling\n│   ├── errors/                     # Core error classes\n│   └── types/                      # Core type definitions\n│\n├── domain/                         # Domain layer\n│   ├── delivery/                   # Delivery context (bounded context)\n│   │   ├── enterprise/             # Enterprise business rules\n│   │   │   ├── entities/           # Domain entities and value objects\n│   │   │   │   ├── admin-person.ts\n│   │   │   │   ├── delivery-person.ts\n│   │   │   │   ├── recipient-person.ts\n│   │   │   │   ├── email-verification.ts\n│   │   │   │   ├── package.ts\n│   │   │   │   ├── package-history.ts\n│   │   │   │   ├── attachments.ts\n│   │   │   │   ├── package-attachment.ts\n│   │   │   │   └── value-object/   # Value objects\n│   │   │   │       ├── cpf.ts\n│   │   │   │       ├── verification-code.ts\n│   │   │   │       ├── package-code.ts\n│   │   │   │       ├── package-status.ts\n│   │   │   │       ├── postal-code.ts\n│   │   │   │       └── package-history-list.ts\n│   │   │   └── events/             # Domain events\n│   │   │       ├── package-registered-event.ts\n│   │   │       ├── package-assigned-to-a-delivery-person-event.ts\n│   │   │       ├── package-picked-up-event.ts\n│   │   │       ├── package-at-distribution-center-event.ts\n│   │   │       ├── package-is-in-transit-event.ts\n│   │   │       ├── package-is-out-for-delivery-event.ts\n│   │   │       ├── package-was-delivered-event.ts\n│   │   │       ├── package-failed-delivery-event.ts\n│   │   │       ├── package-returned-event.ts\n│   │   │       ├── package-was-updated-event.ts\n│   │   │       └── package-canceled-event.ts\n│   │   ├── application/            # Application business rules\n│   │   │   ├── use-cases/          # Use cases (application services)\n│   │   │   │   ├── # Authentication \u0026 Registration\n│   │   │   │   ├── register-admin-person.ts\n│   │   │   │   ├── register-delivery-person.ts\n│   │   │   │   ├── register-recipient-person.ts\n│   │   │   │   ├── authenticate-admin-person.ts\n│   │   │   │   ├── authenticate-delivery-person.ts\n│   │   │   │   ├── authenticate-recipient-person.ts\n│   │   │   │   ├── # Email Verification\n│   │   │   │   ├── send-admin-person-code.ts\n│   │   │   │   ├── send-delivery-person-code.ts\n│   │   │   │   ├── send-recipient-person-code.ts\n│   │   │   │   ├── validate-admin-person-code.ts\n│   │   │   │   ├── validate-delivery-person-code.ts\n│   │   │   │   ├── validate-recipient-person-code.ts\n│   │   │   │   ├── # Password Management\n│   │   │   │   ├── reset-admin-person-password.ts\n│   │   │   │   ├── reset-delivery-person-password.ts\n│   │   │   │   ├── reset-recipient-person-password.ts\n│   │   │   │   ├── # Person Management\n│   │   │   │   ├── update-admin-person.ts\n│   │   │   │   ├── update-delivery-person.ts\n│   │   │   │   ├── update-recipient-person.ts\n│   │   │   │   ├── get-by-id-admin-person.ts\n│   │   │   │   ├── get-by-id-delivery-person.ts\n│   │   │   │   ├── get-by-id-recipient-person.ts\n│   │   │   │   ├── fetch-many-delivery-person.ts\n│   │   │   │   ├── delete-delivery-person.ts\n│   │   │   │   ├── # Package Management\n│   │   │   │   ├── register-package.ts\n│   │   │   │   ├── update-package.ts\n│   │   │   │   ├── get-package-by-id.ts\n│   │   │   │   ├── get-package-by-code.ts\n│   │   │   │   ├── fetch-many-packages.ts\n│   │   │   │   ├── fetch-packages-near-by-delivery-person.ts\n│   │   │   │   ├── assign-package-to-a-delivery-person.ts\n│   │   │   │   ├── picked-up-package.ts\n│   │   │   │   ├── drop-off-package-at-distribution-center.ts\n│   │   │   │   ├── package-is-in-transit.ts\n│   │   │   │   ├── package-is-out-for-delivery.ts\n│   │   │   │   ├── package-was-delivered.ts\n│   │   │   │   ├── package-failed-delivery.ts\n│   │   │   │   ├── return-package.ts\n│   │   │   │   ├── cancel-package.ts\n│   │   │   │   ├── # Attachments\n│   │   │   │   ├── upload-and-create-attachment.ts\n│   │   │   │   ├── # Package History\n│   │   │   │   ├── register-package-history.ts\n│   │   │   │   └── errors/         # Use case errors\n│   │   │   │       ├── person-already-exists-error.ts\n│   │   │   │       ├── wrong-credentials-error.ts\n│   │   │   │       ├── email-code-has-not-been-verified-error.ts\n│   │   │   │       ├── time-to-send-new-email-code-error.ts\n│   │   │   │       ├── resource-not-found-error.ts\n│   │   │   │       ├── email-already-in-use-error.ts\n│   │   │   │       ├── same-email-error.ts\n│   │   │   │       ├── same-password-error.ts\n│   │   │   │       ├── only-admin-can-perform-this-action-error.ts\n│   │   │   │       ├── delivery-person-profile-is-disable-error.ts\n│   │   │   │       ├── delivery-person-not-assigned-to-package-error.ts\n│   │   │   │       ├── cannot-disable-delivery-person-with-active-packages-error.ts\n│   │   │   │       ├── package-already-assigned-error.ts\n│   │   │   │       ├── package-already-canceled-error.ts\n│   │   │   │       ├── package-not-assigned-to-delivery-person-error.ts\n│   │   │   │       ├── delivery-without-required-photo.ts\n│   │   │   │       └── invalid-attachment-type-error.ts\n│   │   │   ├── repositories/       # Repository interfaces\n│   │   │   │   ├── admin-people-repository.ts\n│   │   │   │   ├── delivery-people-repository.ts\n│   │   │   │   ├── recipient-people-repository.ts\n│   │   │   │   ├── packages-repository.ts\n│   │   │   │   ├── packages-history-repository.ts\n│   │   │   │   ├── attachments-repository.ts\n│   │   │   │   ├── package-attachments-repository.ts\n│   │   │   │   └── email-verifications-repository.ts\n│   │   │   ├── email/              # Email service interfaces\n│   │   │   │   └── email-sender.ts\n│   │   │   ├── cryptography/       # Cryptography interfaces\n│   │   │   │   ├── hash-generator.ts\n│   │   │   │   ├── hash-comparer.ts\n│   │   │   │   └── encrypter.ts\n│   │   │   ├── storage/            # Storage interfaces\n│   │   │   │   └── uploader.ts\n│   │   │   └── validation/         # Validation interfaces\n│   │   │       ├── cpf-validator.ts\n│   │   │       ├── password-validator.ts\n│   │   │       └── postal-code-validator.ts\n│   │   └── errors/                 # Domain-specific errors\n│   │       ├── invalidate-cpf-error.ts\n│   │       ├── external-cpf-validation-error.ts\n│   │       ├── invalidate-package-code-error.ts\n│   │       ├── invalidate-package-status-error.ts\n│   │       ├── invalid-postal-code-error.ts\n│   │       ├── external-postal-code-validation-error.ts\n│   │       ├── external-password-validation-error.ts\n│   │       ├── email-code-expired-error.ts\n│   │       ├── invalid-email-code-error.ts\n│   │       ├── delivery-person-already-disabled-error.ts\n│   │       └── missing-attachment-error.ts\n│   │\n│   └── notification/               # Notification context (bounded context)\n│       ├── enterprise/             # Enterprise business rules\n│       │   └── entities/           # Domain entities\n│       │       └── notification.ts\n│       ├── application/            # Application business rules\n│       │   ├── repositories/\n│       │   │   └── notifications-repository.ts\n│       │   └── use-cases/          # Use cases\n│       │       ├── send-notification.ts\n│       │       ├── fetch-many-notifications.ts\n│       │       ├── mark-as-read-notification.ts\n│       │       └── mark-many-notifications-as-read.ts\n│       └── subscribers/            # Event subscribers (cross-boundary communication)\n│           ├── on-package-registered-send-notification.ts\n│           ├── on-package-assigned-send-notification.ts\n│           ├── on-package-picked-up-send-notification.ts\n│           ├── on-package-is-at-a-distribution-center-send-notification.ts\n│           ├── on-package-is-in-transit-send-notification.ts\n│           ├── on-package-was-delivered-send-notification.ts\n│           ├── on-package-failed-delivery-send-notification.ts\n│           ├── on-package-was-updated-send-notification.ts\n│           └── on-package-canceled-send-notification.ts\n│\n└── infra/                          # Infrastructure layer\n    ├── auth/                       # Authentication module\n    │   ├── auth.module.ts\n    │   ├── current-user.decorator.ts\n    │   ├── jwt-auth.guard.ts\n    │   ├── jwt.strategy.ts\n    │   └── public.ts\n    ├── cryptography/               # Cryptography implementations\n    │   ├── argon-hasher.ts        # Argon2 password hashing\n    │   ├── argon-hasher.int-spec.ts\n    │   ├── jwt-encrypter.ts       # JWT encryption\n    │   ├── jwt-encrypter.int-spec.ts\n    │   └── cryptography.module.ts\n    ├── database/                   # Database module\n    │   ├── database.module.ts\n    │   └── drizzle/               # Drizzle ORM\n    │       ├── drizzle.service.ts # Connection pool management\n    │       ├── drizzle.service.int-spec.ts\n    │       ├── mappers/           # Domain ↔ persistence mappers (wip)\n    │       ├── repositories/      # Drizzle repository implementations (wip)\n    │       └── schema/            # Table definitions\n    │           ├── index.ts\n    │           ├── users.ts\n    │           ├── delivery-profiles.ts\n    │           ├── recipient-profiles.ts\n    │           ├── email-codes.ts\n    │           ├── packages.ts\n    │           ├── package-histories.ts\n    │           ├── attachments.ts\n    │           └── notifications.ts\n    ├── email/                      # Email module (Resend)\n    │   ├── build-email-html.ts\n    │   ├── email.service.ts\n    │   ├── email.service.int-spec.ts\n    │   └── email.module.ts\n    ├── env/                        # Environment configuration\n    │   ├── env.ts                 # Zod schema for all env vars\n    │   ├── env.service.ts\n    │   ├── env.service.int-spec.ts\n    │   └── env.module.ts\n    ├── http/                       # HTTP client module\n    │   ├── fetch-http-client.ts   # Fetch-based HTTP client\n    │   ├── fetch-http-client.int-spec.ts\n    │   └── http.module.ts\n    ├── interfaces/                 # Shared response interfaces\n    │   └── postal-code-external-service-response.ts\n    ├── storage/                    # File storage module (Cloudflare R2)\n    │   ├── r2-storage.ts\n    │   ├── r2-storage.int-spec.ts\n    │   └── storage.module.ts\n    ├── validation/                 # External validation services\n    │   ├── password.service.ts    # External password strength validation\n    │   ├── password.service.int-spec.ts\n    │   ├── postal-code.service.ts # External CEP validation\n    │   ├── postal-code.service.int-spec.ts\n    │   └── validation.module.ts\n    ├── tracer.ts                   # OpenTelemetry SDK setup\n    ├── app.module.ts\n    └── main.ts\n```\n\n### Domain Model\n\n#### Entities\n\n- **AdminPerson**: System administrator with full access\n  - Manages delivery persons, packages, and recipients\n  - Can change user passwords\n\n- **DeliveryPerson**: Delivery personnel\n  - Can pick up and deliver packages\n  - Can view assigned packages\n  - Location-based package filtering\n\n- **RecipientPerson**: Package recipient\n  - Registered in the system to receive packages\n  - Associated with delivery addresses\n  - Can track their packages\n\n- **Package**: Delivery package with complete lifecycle\n  - Unique ULID-based tracking code\n  - Status management with state transitions\n  - Assignment to delivery person\n  - Photo attachment for delivery proof\n  - Audit trail with timestamps\n  - Collection of history entries for tracking changes\n\n- **PackageHistory**: Immutable audit log entry for package status changes\n  - Tracks status transitions (from/to)\n  - Records author and delivery person\n  - Includes descriptive notes\n  - Timestamp of the change\n  - Implements domain events for event-driven architecture\n\n- **PackageAttachment**: Photo proof of delivery\n- **Attachments**: File attachments management\n\n- **Notification**: System notifications for recipients\n  - Sent when package events occur\n  - Tracks read/unread status\n  - Associated with recipient\n\n- **EmailVerification**: Email verification management for user authentication\n  - Generates unique 8-digit verification codes\n  - 5-minute expiration window for security\n  - Tracks validation status (validated/pending)\n  - Immutable verification tracking\n\n#### Value Objects\n\n- **CPF**: Brazilian tax ID validation\n  - Format validation (11 digits)\n  - Check digit verification\n  - Duplicate digit rejection\n  - External CPF validation through CpfValidator interface\n  - Returns `Either\u003cError, CPF\u003e` for functional error handling\n\n- **PackageCode**: ULID-based unique identifier\n  - Lexicographically sortable\n  - Timestamp-based generation\n  - Case-insensitive normalization\n  - Future timestamp validation\n\n- **PackageStatus**: Package lifecycle state management\n  - **Valid States**:\n    - `pending` → Initial state\n    - `awaiting_pickup` → Ready for pickup\n    - `picked_up` → Assigned to delivery person\n    - `at_distribution_center` → At distribution center\n    - `in_transit` → On the way\n    - `out_for_delivery` → Out for final delivery\n    - `delivered` → Successfully delivered (final)\n    - `failed_delivery` → Delivery failed\n    - `returned` → Returned to sender (final)\n    - `canceled` → Canceled (final)\n\n  - **State Transitions**: Enforced valid transitions between states\n  - **Final States**: `delivered`, `returned`, `canceled` (no transitions allowed)\n\n- **PostalCode**: Brazilian postal code (CEP) validation\n  - Format validation (8 digits with optional hyphen: 12345-678 or 12345678)\n  - Regex-based pattern matching\n  - External postal code validation through PostalCodeValidator interface\n  - Returns `Either\u003cError, PostalCode\u003e` for functional error handling\n\n- **PackageHistoryList**: Collection of package history entries\n  - Extends WatchedList for tracking changes\n  - Detects new, removed, and current history entries\n  - Enables domain event dispatching for new entries\n\n- **VerificationCode**: 8-digit email verification code value object\n  - Auto-generated using cryptographically secure random integers\n  - Format validation (exactly 8 digits)\n  - Lexicographically comparable\n  - Leading zero preservation\n\n### Domain Events \u0026 Subscribers\n\nThe application uses domain events for cross-bounded-context communication:\n\n#### Events\n\n- **PackageRegisteredEvent**: Dispatched when a package is registered\n- **PackageAssignedToADeliveryPersonEvent**: Dispatched when a package is assigned to a delivery person\n- **PackagePickedUpEvent**: Dispatched when a delivery person picks up a package\n- **PackageAtDistributionCenterEvent**: Dispatched when a package arrives at a distribution center\n- **PackageIsInTransitEvent**: Dispatched when a package is in transit\n- **PackageIsOutForDeliveryEvent**: Dispatched when a package is out for delivery\n- **PackageWasDeliveredEvent**: Dispatched when a package is successfully delivered\n- **PackageFailedDeliveryEvent**: Dispatched when a delivery attempt fails\n- **PackageReturnedEvent**: Dispatched when a package is returned to sender\n- **PackageWasUpdatedEvent**: Dispatched when package details are updated\n- **PackageCanceledEvent**: Dispatched when a package is canceled\n\n#### Subscribers\n\n- **OnPackageRegisteredSendNotification**: Listens to `PackageRegisteredEvent`\n- **OnPackageAssignedToADeliveryPersonSendNotification**: Listens to `PackageAssignedToADeliveryPersonEvent`\n- **OnPackagePickedUpSendNotification**: Listens to `PackagePickedUpEvent`\n- **OnPackageIsAtADistributionCenterSendNotification**: Listens to `PackageAtDistributionCenterEvent`\n- **OnPackageIsInTransitSendNotification**: Listens to `PackageIsInTransitEvent`\n- **OnPackageWasDeliveredSendNotification**: Listens to `PackageWasDeliveredEvent`\n- **OnPackageFailedDeliverySendNotification**: Listens to `PackageFailedDeliveryEvent`\n- **OnPackageWasUpdatedSendNotification**: Listens to `PackageWasUpdatedEvent`\n- **OnPackageCanceledSendNotification**: Listens to `PackageCanceledEvent`\n\n### Package History\n\nPackage history is **automatically created** by the Package entity when state changes occur:\n\n- **Automatic Creation**: No manual use case calls needed\n  - `package.updateStatus()` → Creates history entry\n  - `package.assignDeliveryPerson()` → Creates history entry\n  - `package.markAsRegistered()` → Creates initial history entry\n\n- **Audit Trail**: Each history entry records:\n  - From/To status transition\n  - Author (who made the change)\n  - Delivery person (if applicable)\n  - Description of the change\n  - Timestamp\n\n- **Manual History**: `RegisterPackageHistoryUseCase` exists for administrative purposes\n  - Used for manual corrections or special audit entries\n  - Not used in normal package lifecycle\n\n### Package Lifecycle Flow\n\n```\npending\n  ↓\nawaiting_pickup ──────────────┐\n  ↓                           │\npicked_up ────────────────────┤\n  ↓                           │\nat_distribution_center        │\n  ↓           ↕               │\nin_transit ───────────────────┤ → canceled\n  ↓                           │\nout_for_delivery ─────────────┤\n  ↓           ↓               │\ndelivered   failed_delivery   │\n              ↓               │\n            returned ─────────┘\n```\n\n## 🔐 Authentication \u0026 Authorization\n\n- **JWT-based authentication**: Secure token-based auth\n- **Role-Based Access Control (RBAC)**: Permission management\n- **Three user roles**: Admin, Delivery Person, and Recipient with different permissions\n- **Login with CPF and password**: Brazilian tax ID authentication\n- **Password hashing**: Secure password storage using cryptography layer\n- **Email verification requirement**: Users must verify their email before authentication\n- **Time-limited verification codes**: 5-minute expiration window for security\n\n### User Roles \u0026 Permissions\n\n#### Admin\n- ✅ Create, read, update, delete delivery persons\n- ✅ Create, read, update, delete packages\n- ✅ Create, read, update, delete recipients\n- ✅ Change user passwords\n- ✅ View all deliveries and packages\n\n#### Delivery Person\n- ✅ View assigned packages\n- ✅ Pick up packages\n- ✅ Mark packages as delivered (with photo proof)\n- ✅ Mark packages as returned\n- ✅ View nearby packages based on location\n- ❌ Cannot view other delivery persons' packages\n- ❌ Cannot modify packages not assigned to them\n\n## 📊 CI/CD Pipeline\n\nThe project uses GitHub Actions for continuous integration and deployment:\n\n- **Code Quality**: Biome checks, linting, and type checking\n- **Testing**: Unit and E2E tests (when enabled)\n- **Semantic Release**: Automated versioning and changelog generation\n- **Docker**: Multi-architecture builds (linux/amd64, linux/arm64)\n- **Docker Hub**: Automated image publishing\n\n## 📝 API Documentation\n\nAPI documentation is available through Swagger/OpenAPI.\n\nOnce the server is running, access the documentation at:\n```\nhttp://localhost:3333/api/docs\n```\n\n## 🧪 Testing\n\nThe project includes three levels of testing with Vitest:\n\n### Unit Tests (`.spec.ts`)\n\nTest domain logic in complete isolation using in-memory repositories and fakes:\n\n- Value object validation (CPF, PackageCode, PackageStatus, PostalCode, VerificationCode)\n- Entity logic (EmailVerification expiration, validation status)\n- Use case business logic (RegisterAdminPerson, RegisterDeliveryPerson, RegisterRecipientPerson, AuthenticateAdminPerson, AuthenticateDeliveryPerson, AuthenticateRecipientPerson, RegisterPackage, UpdatePackage, AssignPackageToADeliveryPerson, PickedUpPackage, DropOffPackageAtDistributionCenter, PackageIsInTransit, PackageIsOutForDelivery, PackageWasDelivered, PackageFailedDelivery, ReturnPackage, CancelPackage, FetchManyPackages, FetchPackagesNearByDeliveryPerson, ValidatePersonCode, ResetPersonPassword, UpdatePerson, DeleteDeliveryPerson, UploadAndCreateAttachment, FetchManyNotifications, MarkAsReadNotification, MarkManyNotificationsAsRead)\n- Email verification requirement in authentication flow\n- Domain event subscribers (OnPackageRegisteredSendNotification, OnPackageAssignedToADeliveryPersonSendNotification, OnPackagePickedUpSendNotification, OnPackageIsAtADistributionCenterSendNotification, OnPackageIsInTransitSendNotification, OnPackageWasDeliveredSendNotification, OnPackageFailedDeliverySendNotification, OnPackageWasUpdatedSendNotification, OnPackageCanceledSendNotification)\n- Comprehensive test coverage with 200+ passing tests\n\n### Integration Tests (`.int-spec.ts`)\n\nTest infrastructure services against real external systems (database, email, storage, external APIs). Each integration test spins up a NestJS app via `makeModuleRef`:\n\n| Test file | What it covers |\n|---|---|\n| `drizzle.service.int-spec.ts` | Database connection and query execution |\n| `argon-hasher.int-spec.ts` | Argon2 password hashing and verification |\n| `jwt-encrypter.int-spec.ts` | JWT sign and verify |\n| `env.service.int-spec.ts` | Environment variable loading and validation |\n| `email.service.int-spec.ts` | Resend email delivery |\n| `fetch-http-client.int-spec.ts` | HTTP client (external service calls) |\n| `r2-storage.int-spec.ts` | Cloudflare R2 file upload |\n| `password.service.int-spec.ts` | External password strength validation |\n| `postal-code.service.int-spec.ts` | ViaCEP postal code lookup |\n\n### E2E Tests\n\nTesting complete user flows, API endpoints, full request/response cycles, and database integration.\n\n### Coverage Reports\n\nTrack code coverage metrics with Vitest coverage tools.\n\n### Test Structure\n\n```\ntest/\n├── setup-e2e.ts            # E2E test setup\n├── drop-uuid-schema.ts     # DB cleanup helper\n├── cryptography/           # Fake cryptography implementations\n│   ├── fake-hasher.ts\n│   └── faker-encrypter.ts\n├── email/\n│   └── fake-email-sender.ts\n├── factories/              # Test data factories\n│   ├── make-admin-person.ts\n│   ├── make-delivery-person.ts\n│   ├── make-recipient-person.ts\n│   ├── make-package.ts\n│   ├── make-package-attachment.ts\n│   ├── make-package-history.ts\n│   ├── make-attachment.ts\n│   ├── make-notification.ts\n│   └── make-module-ref.ts  # NestJS app factory for integration tests\n├── repositories/           # In-memory repository implementations\n│   ├── in-memory-admin-people-repository.ts\n│   ├── in-memory-delivery-people-repository.ts\n│   ├── in-memory-recipient-people-repository.ts\n│   ├── in-memory-packages-repository.ts\n│   ├── in-memory-packages-history-repository.ts\n│   ├── in-memory-notifications-repository.ts\n│   ├── in-memory-attachments-repository.ts\n│   └── in-memory-package-attachments-repository.ts\n├── storage/\n│   └── fake-uploader.ts\n├── validation/\n│   ├── fake-password-validator.ts\n│   └── fake-postal-code-validator.ts\n└── utils/\n    ├── generate-future-ulid.ts  # ULID generator with future timestamp\n    ├── wait-for.ts              # Async polling helper for domain events\n    └── assets/\n        └── file-to-use-on-upload.png\n```\n\n## 🗃️ Database\n\n- **PostgreSQL**: Primary database (managed via Docker Compose)\n- **ORM**: Drizzle ORM with `drizzle-orm/node-postgres` driver\n- **Automatic Setup**: Run `pnpm run prestart:dev` to start PostgreSQL\n- **Environment Variables**: Configure database connection in `.env` file\n\n### Schema Tables\n\n| Table | Description |\n|---|---|\n| `users` | All user accounts (Admin, DeliveryPerson, RecipientPerson) with role enum |\n| `delivery_profiles` | Delivery-person-specific data (`isActive`) |\n| `recipient_profiles` | Recipient-specific extension marker |\n| `email_codes` | Email verification codes with `validatedAt` tracking |\n| `packages` | Package lifecycle data with `packageStatusEnum` constraint |\n| `package_histories` | Immutable audit log of package status transitions |\n| `attachments` | Uploaded files (delivery proof photos) |\n| `notifications` | Recipient notifications with read tracking |\n\n### Required Environment Variables\n\nCreate a `.env` file in the root directory:\n\n```env\n# Server\nPORT=3000\nNODE_ENV=\"dev\"  # Options: dev, test, production\nCORS_ORIGIN=\"http://localhost:3000\"\n\n# JWT (RS256 - Public/Private Key Authentication)\n# Generate keys with:\n# Private: openssl genrsa -out private_key.pem 2048\n# Public: openssl rsa -in private_key.pem -pubout -out public_key.pem\n# Then encode to base64:\n# JWT_PRIVATE_KEY=$(cat private_key.pem | base64)\n# JWT_PUBLIC_KEY=$(cat public_key.pem | base64)\nJWT_PRIVATE_KEY=\"base64-encoded-private-key\"\nJWT_PUBLIC_KEY=\"base64-encoded-public-key\"\n\n# Database\nDATABASE_URL=\"postgresql://user:password@localhost:5432/fastfeet\"\nDATABASE_PORT=5432\nDATABASE_USERNAME=\"user\"\nDATABASE_PASSWORD=\"password\"\nDATABASE_NAME=\"fastfeet\"\n\n# Password hashing\nARGON2_PEPPER=\"random-pepper-string\"\n\n# Email (Resend)\nRESEND_API_KEY=\"re_xxxxxxxxxxxx\"\nEMAIL=\"noreply@yourdomain.com\"\n\n# External services\nPOSTAL_CODE_EXTERNAL_SERVICE_URL=\"https://viacep.com.br/ws\"\n\n# File storage (Cloudflare R2)\nCLOUDFLARE_ACCOUNT_ID=\"your-account-id\"\nCLOUDFLARE_ACCOUNT_TOKEN=\"your-account-token\"\nAWS_BUCKET_NAME=\"your-bucket-name\"\nAWS_ACCESS_KEY_ID=\"your-access-key\"\nAWS_SECRETE_ACCESS_KEY_ID=\"your-secret-key\"\n\n# Test environment only\nJSON_PLACEHOLDER_URL=\"https://jsonplaceholder.typicode.com\"\nHTTPBIN_URL=\"https://httpbin.org\"\n```\n\n## 🔍 Key Features\n\n### Implemented ✅\n- Domain entities with DDD principles (AdminPerson, DeliveryPerson, RecipientPerson, Package, PackageHistory, Notification, EmailVerification)\n- Value objects with validation (CPF, PackageCode, PackageStatus, PostalCode, VerificationCode)\n- Package status state machine with transition rules\n- User registration (Admin, Delivery Person, and Recipient)\n  - Password validation with external validator interface\n  - Automatic email verification creation\n- User authentication use cases (Admin, Delivery Person, and Recipient)\n  - JWT token generation with encryption layer\n  - Password comparison with hash comparer\n  - Credential validation with wrong credentials error handling\n  - Email verification requirement before authentication\n  - Time-limited verification codes (5-minute expiration)\n- Person management use cases (update, get by ID, fetch many, delete)\n  - Admin person management\n  - Delivery person management (with active packages guard on delete)\n  - Recipient person management\n- Password reset use cases for all user types\n- Package management use cases\n  - Package registration with postal code validation\n  - Package update\n  - Package retrieval (by ID and by code)\n  - Package listing with pagination and filtering\n  - Location-based package filtering for delivery persons\n  - Package assignment to delivery person with automatic status updates\n  - Full package lifecycle: pickup → distribution center → in transit → out for delivery → delivered / failed delivery → returned\n  - Package cancellation\n  - Photo attachment upload for delivery proof (UploadAndCreateAttachment)\n- Notification management use cases\n  - Fetch many notifications (with pagination)\n  - Mark notification as read\n  - Mark many notifications as read\n- Password hashing with cryptography layer (Argon2 via ArgoHasher)\n- JWT encryption implementation (JwtEncrypter)\n- Auth module with JWT strategy, guards, and decorators\n- External CPF validation with dependency injection pattern\n- External postal code validation with dependency injection pattern\n- External password strength validation with dependency injection pattern\n- File storage abstraction with Uploader interface\n- Repository pattern with in-memory implementations for testing\n- Domain events infrastructure for event-driven architecture\n- Event subscribers for cross-boundary communication\n  - Package registered notification\n  - Package assigned notification\n  - Package picked up notification\n  - Package at distribution center notification\n  - Package in transit notification\n  - Package was delivered notification\n  - Package failed delivery notification\n  - Package was updated notification\n  - Package canceled notification\n- Package history tracking with automatic audit trail\n  - Automatic creation on status changes\n  - Automatic creation on delivery person assignment\n  - Manual use case for administrative entries\n- WatchedList pattern for tracking collection changes\n- Notification system for recipients\n- Email verification system with time-limited codes\n  - 8-digit cryptographically secure verification codes\n  - 5-minute expiration window\n  - Validation status tracking\n  - Send verification code use cases for all user types (Admin, Delivery Person, Recipient)\n  - Rate limiting to prevent code spam (can't request new code until current expires)\n  - Email service abstraction with EmailSender interface\n- Comprehensive unit tests for domain logic (200+ passing tests)\n  - Email verification expiration logic tests\n  - Authentication with unverified email rejection tests\n  - Verification code format validation tests\n- Test data factories for easy test setup with automatic email verification\n- Functional error handling with Either monad pattern\n\n### Infrastructure ✅\n\n- **Database**: Drizzle ORM with PostgreSQL — connection pool, schema definitions with enums, indexes, FK constraints\n- **Email**: Resend integration for sending verification codes\n- **File Storage**: Cloudflare R2 (S3-compatible) for delivery proof photos\n- **HTTP Client**: Fetch-based client for external service calls (ViaCEP postal code lookup)\n- **Password Validation**: External password strength validation service\n- **Observability**: OpenTelemetry SDK with OTLP trace and log exporters\n- **Environment**: Zod-validated environment configuration with per-environment rules\n- **Integration Tests**: 9 integration test suites covering all infrastructure services\n\n### In Progress 🚧\n- Drizzle repository implementations and domain mappers\n- HTTP/REST API endpoints with NestJS controllers\n- Package CRUD operations API\n- Recipient management API\n- Photo upload for delivery proof\n- Location-based package filtering\n- E2E tests\n\n## 🤝 Contributing\n\nThis is a portfolio project, but suggestions and feedback are welcome!\n\n### Development Workflow\n\n1. **Create a new branch**\n   ```bash\n   git checkout -b feature/your-feature-name\n   ```\n\n2. **Make your changes** following the project conventions:\n   - Use conventional commits (feat, fix, chore, test, refactor, docs)\n   - Write unit tests for new features\n   - Follow the existing code structure and patterns\n\n3. **Run quality checks**\n   ```bash\n   pnpm run verify\n   ```\n\n4. **Commit your changes**\n   ```bash\n   git commit -m \"feat: add new feature\"\n   ```\n\n5. **Push and create a pull request**\n   ```bash\n   git push origin feature/your-feature-name\n   ```\n\n### Commit Convention\n\nThis project uses [Conventional Commits](https://www.conventionalcommits.org/):\n\n- `feat:` New feature\n- `fix:` Bug fix\n- `docs:` Documentation changes\n- `test:` Adding or updating tests\n- `refactor:` Code refactoring\n- `chore:` Maintenance tasks\n- `perf:` Performance improvements\n\nSemantic Release automatically generates versions and changelogs based on commit messages.\n\n## 📄 License\n\nUNLICENSED - This is a course challenge project.\n\n## 👤 Author\n\nBuilt as part of a portfolio project based on a course challenge.\n\n## 🙏 Acknowledgments\n\n- Course challenge based on Rocketseat's Node.js learning path\n- Built with NestJS, following DDD and Clean Architecture principles\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fviniciusferreira7%2Ffast-feet-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fviniciusferreira7%2Ffast-feet-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fviniciusferreira7%2Ffast-feet-api/lists"}