diego3g/umbriel
41.4
Weak · 7 October 2026
7k
lines of production code
TypeScript
primary language
4
measurements over time
What this system is
This system is a backend service for managing email marketing campaigns, providing capabilities to create and send broadcast messages using customizable templates. It maintains a database of contacts and tags to segment audiences, while tracking detailed delivery metrics such as opens, clicks, and bounces via AWS SNS webhooks. The architecture supports asynchronous message delivery through a queue system and synchronizes contact data from external integrations via Kafka.
Features
Ability to set a default message template
Users can now designate a specific message template as the default for broadcasts. This is achieved via a new PATCH endpoint at \/templates/:templateId/set-as-default\, which automatically unsets the previous default (if any) and marks the selected template as the new default, ensuring only one template holds this status at a time.
src/modules/broadcasting/useCases/SetDefaultTemplate · high confidence
Ability to set a default sender
Users can now designate a specific sender as the default by calling the new PATCH /senders/:id/set-as-default endpoint. This action automatically unsets the default status on any previously selected sender, ensuring that only one sender holds the default flag at any time.
src/modules/senders/useCases/SetDefaultSender · high confidence
Accounts module domain model and data access layer
The accounts module now includes a complete domain model for users, featuring value objects for email, name, and password with built-in validation (e.g., email format, password length 6-255 chars) and secure password handling via bcrypt hashing. A JWT utility class supports signing, verifying, and decoding tokens for authentication flows. Data persistence is abstracted through an \IUsersRepository\ interface with implementations for both in-memory testing and Prisma-based database operations, including a mapper to translate between domain entities and database records.
src/modules/accounts · high confidence
Add ability to block a contact
Users can now block a contact via a new PATCH endpoint at /contacts/{contactId}/block. This change introduces the BlockContact use case, its controller, and the associated ContactNotFoundError, along with unit and end-to-end tests to verify that the contact's blocked status is correctly updated.
src/modules/subscriptions/useCases/BlockContact · high confidence
Add ability to create message templates via API
Users can now create message templates by sending a POST request to the /templates endpoint with a title and content. The system validates that the title meets length requirements and that the content includes the required {{ message\_content }} variable; valid templates are persisted and return a 201 status, while invalid inputs return a 400 error.
src/modules/broadcasting/useCases/CreateTemplate · high confidence
Add ability to create new contacts via API
Users can now create new contacts by sending a POST request to the /contacts endpoint with a name and email. The system validates the input, rejecting requests with empty names or invalid email formats, and returns a 201 Created status upon successful creation.
src/modules/subscriptions/useCases/CreateContact · high confidence
Add ability to create tags via API
Users can now create tags by sending a POST request to the /tags endpoint with a title. This change introduces the CreateTag use case, its controller, and the corresponding unit and end-to-end tests to validate the creation flow and title validation.
src/modules/subscriptions/useCases/CreateTag · high confidence
Add ability to delete a contact from an integration
A new use case, DeleteContactFromIntegration, has been introduced to allow users to remove a contact associated with a specific integration. This feature locates a contact by its integration ID and deletes it from the repository, returning a success result if the contact is found and removed, or a ContactNotFoundError if the contact does not exist. The implementation includes the core use case logic, a custom error class for missing contacts, and unit tests verifying both successful deletion and handling of non-existent contacts.
src/modules/subscriptions/useCases/DeleteContactFromIntegration · high confidence
Add ability to retrieve all senders
Users can now retrieve a list of all senders via the GET /senders endpoint. This change introduces the GetAllSenders use case, its HTTP controller, and the corresponding unit and end-to-end tests to verify that the endpoint correctly returns sender details (id, name, email) for authenticated users.
src/modules/senders/useCases/GetAllSenders · high confidence
Add broadcasting mappers and DTOs for message details and stats
This change introduces the data-mapping layer for the broadcasting module, adding mappers to convert between Prisma persistence models and domain entities for messages, recipients, templates, tags, and events. It also defines DTOs for message details (including sender, template, and tags) and message statistics, with the stats mapper calculating open and click rates from raw event counts.
src/modules/broadcasting/mappers · high confidence
Add contact search with pagination and case-insensitive filtering
Users can now search for contacts via the /contacts/search endpoint, supporting optional query text, page, and per\_page parameters. The search is case-insensitive and returns both the matching contact list and a totalCount, enabling efficient pagination in the UI.
src/modules/subscriptions/useCases/SearchContacts · high confidence
Add contact unsubscription capability
Users can now unsubscribe a contact from subscriptions via a new PATCH endpoint at /contacts/{contactId}/unsubscribe. This change introduces the UnsubscribeContact use case, its HTTP controller, and the associated ContactNotFoundError, along with unit and end-to-end tests to verify the behavior.
src/modules/subscriptions/useCases/UnsubscribeContact · high confidence
Add endpoint to retrieve all broadcast templates
Users can now fetch a list of all available broadcast templates via a new GET /templates endpoint. This change introduces the GetAllTemplates use case, which retrieves all templates from the repository, and a corresponding controller that exposes this data through the API, returning the template ID and title for each entry.
src/modules/broadcasting/useCases/GetAllTemplates · high confidence
Add endpoint to retrieve all subscription tags
Users can now fetch a complete list of all available tags via the GET /tags endpoint. This change introduces the GetAllTags use case and its corresponding controller, which queries the tags repository and returns the tag IDs and titles in the response body.
src/modules/subscriptions/useCases/GetAllTags · high confidence
Add endpoint to retrieve broadcast message details
Users can now fetch the full details of a specific broadcast message, including its subject, body, sender information, and associated tags, via a new GET route at /messages/:id. This change introduces the GetMessageDetails use case, its HTTP controller, and the corresponding unit and end-to-end tests to verify the functionality.
src/modules/broadcasting/useCases/GetMessageDetails · high confidence
Add endpoint to retrieve detailed contact information
Users can now fetch comprehensive details for a specific contact via a new GET /contacts/:id endpoint. The response includes the contact's name and email, along with associated subscriptions (including tag titles) and message history (including subject, body, and events like opens). This capability is implemented through a new use case and controller, backed by unit and end-to-end tests.
src/modules/subscriptions/useCases/GetContactDetails · high confidence
Add message creation and preview capabilities
Users can now create broadcast messages via a new POST /messages endpoint, specifying a subject, body, sender, and target tags, with optional template support and validation for empty tags or invalid templates. Additionally, a new POST /messages/:id/preview endpoint allows sending a rendered preview of a message to a specific email address, substituting template variables with the message body content before delivery.
src/modules/broadcasting/useCases/CreateMessage · high confidence
Add message search with case-insensitive filtering and pagination
Users can now search for messages via the /messages/search endpoint, supporting case-insensitive queries and pagination through page and per\_page parameters. The search returns message details including subject, body, and sent date, allowing users to efficiently locate specific communications within the broadcasting system.
src/modules/broadcasting/useCases/SearchMessages · high confidence
Add message statistics endpoint
Introduces a new GET /messages/:messageId/stats route that returns delivery, open, and click metrics for a specific broadcast message. The response includes the total recipient count, the number of delivered messages, the open rate, the click count, and the click rate, calculated based on distinct recipient events.
src/modules/broadcasting/useCases/GetMessageStats · high confidence
Add sender creation and removal capabilities
Users can now create and remove senders. The new CreateSender use case validates the sender's name and email before persisting the record, returning a 201 Created response on success or a client error for invalid input. The new RemoveSender use case allows deleting a sender by ID via a DELETE request, returning a 200 OK response upon successful removal.
src/modules/senders/useCases/CreateSender · high confidence
Add sender search with pagination and case-insensitive filtering
Users can now search for senders via a new GET /senders/search endpoint. The search supports case-insensitive matching on sender names, allows filtering by a query string, and includes pagination controls (page and per\_page) to manage result sets. The response includes both the paginated list of senders and a totalCount field indicating the total number of matching records.
src/modules/senders/useCases/SearchSenders · high confidence
Add tag search with pagination and case-insensitive filtering
Users can now search for tags via the /tags/search endpoint, supporting optional query, page, and per\_page parameters. The search is case-insensitive and returns both the matching tag data and a totalCount for pagination purposes.
src/modules/subscriptions/useCases/SearchTags · high confidence
Add template preview capability
Users can now preview how a broadcast template will render by sending HTML content to the new \/templates/preview\ endpoint. The system composes the provided template with sample content (including example headings and links) to generate a realistic preview, allowing users to verify the appearance of their messages before sending.
src/modules/broadcasting/useCases/PreviewTemplate · high confidence
Add template search capability with pagination and case-insensitive filtering
Users can now search for message templates via a new GET /templates/search endpoint. The search supports case-insensitive matching on template titles, allows filtering by a query string, and includes pagination controls (page and per\_page parameters). The response includes the list of matching templates (id, title, isDefault) and a totalCount field indicating the total number of matches across all pages.
src/modules/broadcasting/useCases/SearchTemplates · high confidence
Add use case for delivering broadcast messages via email
A new DeliverMessageToRecipient use case has been introduced to handle the delivery of broadcast messages. It accepts message, sender, and recipient details and delegates the actual email sending to the configured mail provider, ensuring that the message ID and contact ID are passed along with the email payload. Unit tests have been added to verify that the email sending method is invoked correctly with the expected parameters.
src/modules/broadcasting/useCases/DeliverMessageToRecipient · high confidence
Add use case to update subscription tag titles from integrations
Users can now update the title of a subscription tag via an integration. This change introduces the UpdateTagFromIntegration use case, which accepts a tag's integration ID and a new title, validates the title length, and persists the change. It handles cases where the tag is not found or the title is invalid.
src/modules/subscriptions/useCases/UpdateTagFromIntegration · high confidence
Added Prisma client initialization and database seeding script
The Prisma infrastructure layer now includes a dedicated client singleton for database connections and a seed script to populate initial data. The seed script creates sample tags and contacts, establishing the foundational data structure for the application's contact management features.
src/infra/prisma · high confidence
Added Recipient domain model and unit tests
Introduced the Recipient entity within the broadcasting module to represent a recipient of a message, linking a specific message ID and contact ID. The model includes an events collection and provides a method to add event records, enabling the tracking of delivery status or other interactions associated with that recipient.
src/modules/broadcasting/domain/recipient · high confidence
Added authentication middleware and access denied error
Users can now have their requests validated via an authentication middleware that checks for a valid access token. The new EnsureAuthenticatedMiddleware verifies the provided JWT access token; if valid, it proceeds, but if the token is missing or invalid, the request is rejected with a 403 Forbidden response using the new AccessDeniedError.
src/infra/http/errors, src/infra/http/middlewares · high confidence
Added configuration for authentication, mail, and queue services
New configuration files have been introduced to define settings for core services. Authentication is now configured with a specific secret key and a token expiration time of one day. Mail delivery is set up to use the Mailtrap driver by default, with specific SMTP connection details, while also defining an Amazon SES driver with a maximum send rate of 400 messages. Additionally, the queue system is configured to use the Bull driver.
src/config · high confidence
Added contact and tag creation services with Kafka integration adapter
This change introduces the core logic for creating contacts and tags within the subscriptions module, along with an adapter to process incoming Kafka messages. Specifically, it adds \createContact\ and \createTag\ services that validate input (name, email, title) and return typed results using the \Either\ pattern. Additionally, a \KafkaHandlerAdapter\ is provided to bridge Kafka messages to the domain handler, enabling the system to subscribe contacts via Kafka integration.
src/infra/kafka/adapters, src/modules/subscriptions/domain/contact/services, src/modules/subscriptions/domain/tag/services · high confidence
Added core domain primitives and error interfaces
Introduced foundational domain-layer components including an abstract Entity base class with automatic ID generation and equality checks, a WatchedList collection that tracks added and removed items, and standard error interfaces (DomainError, UseCaseError) to support consistent error handling in use cases.
src/core/domain · high confidence
Added scaffolding generator for use cases and controllers
Developers can now use the Plop CLI to scaffold a new use case and its associated HTTP controller. The generator creates the use case class, its unit test, an optional HTTP controller with error handling, the controller's end-to-end test, and a dependency-injection factory, placing them in the appropriate module directories.
.plop · high confidence
Added startup scripts for Kafka, Queue, HTTP Server, and Webhook services
New executable shell scripts have been added to the scripts directory to standardize the startup process for the application's infrastructure components. The scripts kafka.sh, queue.sh, server.sh, and webhook.sh each handle database migrations and Prisma code generation before launching their respective Node.js processes (kafka/app.js, queue/worker.js, http/server.js, and sns-webhook/server.js). This ensures that database schemas are up-to-date and code is generated before the services start.
scripts · high confidence
Count recipients by tags
Added a new capability to count unique contacts subscribed to specific tags. This includes the \CountRecipientsFromTags\ use case, a corresponding HTTP controller, and unit/e2e tests. The feature exposes a \/recipients/count\ endpoint that accepts an array of tag IDs and returns the total number of unique recipients matching those tags.
src/modules/broadcasting/useCases/CountRecipientsFromTags · high confidence
Dedicated SNS webhook server for handling Amazon SNS notifications
A new standalone server has been introduced in the \src/infra/sns-webhook\ directory to handle Amazon SNS webhook events, separating this responsibility from the main HTTP server. This service exposes a POST endpoint at \/events/notifications\ that processes incoming SNS messages. It includes an \AmazonSNSValidatorMiddleware\ to validate message signatures in production environments and automatically handles Subscription and Unsubscribe confirmation requests by hitting the provided SubscribeURL. Validated messages are routed to a \RegisterEventController\, which utilizes repositories for recipients, contacts, and subscriptions to process the event data.
src/infra/sns-webhook · high confidence
Define interface for message delivery job data
Added the IDeliverMessageJob interface to define the structure of data passed to message delivery jobs, including sender details, recipient information, and message content (id, subject, body).
src/modules/broadcasting/jobs · high confidence
Expanded Prisma schema and test environment setup
The Prisma data layer has been significantly expanded to support core messaging features, introducing new models for Users, Templates, Tags, Contacts, Subscriptions, Messages, Senders, Recipients, and Events, along with a new EventType enum. The schema now includes audit fields (created\_at, updated\_at) on most models and enables Prisma preview features like selectRelationCount and nApi. Additionally, a dedicated Jest test environment has been added to manage isolated database schemas for testing, and the .env configuration has been standardized.
prisma · high confidence
Express Request type augmentation for user identification
The application now supports attaching a user identifier to Express request objects. A new TypeScript declaration file augments the Express Request interface to include a userId property, enabling type-safe access to the authenticated user's ID within request handlers.
src/@types · high confidence
HTTP controller factories wired to Prisma repositories and use cases
The \src/infra/http/factories\ layer now provides factory functions for all HTTP controllers, wiring each controller to its corresponding Prisma repository and use case. This includes factories for authentication, user registration (with validator composition), contact management (create, search, details, block, subscribe/unsubscribe to tags), sender management (create, search, list, remove, set default), template management (create, search, list, preview, set default), and message broadcasting (create, search, details, stats, send via Bull queue, send preview via Amazon SES). An authentication middleware factory is also included.
src/infra/http/factories · high confidence
In-memory repository implementations for broadcasting domain entities
This change introduces in-memory repository implementations for the broadcasting module, providing temporary storage for messages, templates, recipients, and message tags. These repositories support core operations such as creating and saving entities, searching with case-insensitive query filtering and pagination, retrieving message statistics (clicks, deliveries, opens), and fetching message details including sender and template information. They serve as the in-memory data layer for the broadcasting feature, enabling testing and development without a persistent database.
src/modules/broadcasting/repositories/in-memory · high confidence
Initial HTTP API route definitions for core resources
This change introduces the Express router definitions for the application's core HTTP endpoints, establishing the URL structure for users, sessions, contacts, messages, senders, tags, templates, and recipients. It wires up specific routes such as user registration and authentication, contact management (create, search, block, unsubscribe), message operations (send, preview, stats), and resource management for senders, tags, and templates, all protected by an authentication middleware where applicable.
src/infra/http/routes · high confidence
Initial HTTP server setup with CORS and JSON parsing
The HTTP infrastructure now initializes an Express application that enables Cross-Origin Resource Sharing (CORS) with specific exposed headers (x-total-count, Content-Type, Content-Length) and parses incoming JSON or plain text payloads. The server loads environment variables using dotenv-flow and starts listening on the port defined by the PORT environment variable.
src/infra/http · high confidence
Initial Kafka consumer integration for contact and team events
The application now includes a new Kafka consumer infrastructure (src/infra/kafka) that connects to the configured brokers and subscribes to five specific topics: tag subscription/unsubscription, user info updates, user deletion, and team info changes. This consumer routes incoming messages to dedicated handlers, enabling the system to react to external events regarding contact lifecycle and team metadata updates.
src/infra/kafka · high confidence
Introduce Prisma-based persistence layer for the broadcasting module
The broadcasting module now uses a new set of Prisma repositories to manage data persistence for messages, templates, recipients, message tags, and events. This change provides concrete database implementations for the module's domain entities, enabling features such as message search with case-insensitive filtering, template management (including default template retrieval), recipient tracking with event upserts, and message statistics aggregation. The repository layer handles the mapping between domain objects and the Prisma client, supporting operations like creating and updating messages with their associated tags, searching templates and messages with pagination, and recording event data for recipients.
src/modules/broadcasting/repositories/prisma · high confidence
Introduce Sender domain model with email and name validation
Added domain entities for the Senders module, including a Sender aggregate root and value objects for Email and Name. The Email value object enforces format validation (regex) and length limits (max 255 characters), while the Name value object ensures a minimum length of 2 characters and a maximum of 255 characters. The Sender entity supports setting a default sender and tracks validation status, providing a structured foundation for managing sender identities within the application.
src/modules/senders/domain · high confidence
Introduce SenderMapper for domain-persistence conversion
A new SenderMapper class has been added to handle the conversion between the Sender domain model and the persistence layer. This mapper ensures that sender names and emails are validated during the transformation from raw database records and correctly maps the is\_validated and is\_default flags to their respective domain properties.
src/modules/senders/mappers · high confidence
Introduce contact domain model with subscription and status management
Added the core domain entities for the contact module, including the Contact aggregate root, Email and Name value objects, and Subscription entities. The Contact model now enforces validation for email addresses and names, tracks subscription tags via a dedicated Subscriptions collection, and manages contact lifecycle states such as blocked, unsubscribed, and bounced statuses to determine mailing eligibility.
src/modules/subscriptions/domain/contact · high confidence
Introduce domain models for broadcasting event types
Added the core domain entities for the broadcasting module, including an Event model and a Type value object that restricts event types to specific valid values (DELIVER, OPEN, CLICK, BOUNCE, COMPLAINT, REJECT). This change introduces validation logic to ensure only recognized event types are created, along with corresponding error handling and unit tests for the new domain structures.
src/modules/broadcasting/domain/event · high confidence
Introduce message domain model with validation rules
The broadcasting module now includes a domain model for messages, defining value objects for the subject (4–80 characters) and body (minimum 20 characters) with specific error types for length violations. The core Message entity supports tagging via MessageTag/MessageTags and includes a deliver method that records the delivery timestamp and recipient count, alongside a sender identifier.
src/modules/broadcasting/domain/message · high confidence
Introduce pluggable email and message queue providers
The infrastructure layer now supports configurable email delivery and message queuing via new provider implementations. For email, you can choose between Amazon SES (with configuration set and metadata tagging), Mailtrap (for testing via nodemailer), or a synchronous logging provider that prints message details to the console. For queuing, the system supports asynchronous processing via BullMQ (configured with Redis, exponential backoff, and concurrency limits) or a synchronous in-memory provider for development and testing. These providers implement the \IMailProvider\ and \IMailQueueProvider\ interfaces, allowing the application to switch delivery mechanisms without changing core business logic.
src/infra/providers · high confidence
Introduce queued message broadcasting with template support
The SendMessage use case now delivers messages via a background mail queue instead of sending them synchronously. When a message is sent, the system resolves the associated tags to find only subscribed contacts, and if a template is attached, it composes the final body using the template content and inlines the CSS before dispatch. The operation records the sent timestamp and recipient count, and prevents duplicate sends by rejecting messages that have already been delivered.
src/modules/broadcasting/useCases/SendMessage · high confidence
Introduce repository interfaces and in-memory/Prisma implementations for contacts, tags, and subscriptions
This change adds the data-access layer for the subscriptions module, defining interfaces (IContactsRepository, ISubscriptionsRepository, ITagsRepository) and providing both in-memory and Prisma-based implementations. Users gain the ability to search contacts and tags with pagination and case-insensitive filtering, retrieve contact details including subscription and message history, count and find subscribers by tags while excluding bounced, unsubscribed, or blocked contacts, and manage subscription records (create, save, delete) via a persistence-agnostic layer.
src/modules/subscriptions/repositories · high confidence
Introduce subscription module data mappers and DTOs
This change adds the mapping layer and data transfer objects for the new subscriptions module, enabling the system to translate between persistence models and domain entities. Specifically, it introduces mappers for Contact, Subscription, Tag, and TagWithSubscribers, along with DTOs like ContactWithDetails and TagWithSubscribersCount, which structure contact information including subscriptions, messages, and subscriber counts for API responses.
src/modules/subscriptions/mappers · high confidence
Introduce template domain model with content composition and validation
This change introduces the core domain model for broadcast templates, defining \Template\, \Content\, and \Title\ as value objects/entities. Users can now create templates with validated titles (4–250 characters) and content that must include the \{{ message\_content }}\ placeholder. The \Content\ object supports a \compose\ method to substitute the placeholder with actual message text, and templates support a default flag that can be set or unset.
src/modules/broadcasting/domain/template · high confidence
Introduces core HTTP infrastructure interfaces and Express adapters
The \src/core/infra\ layer now provides the foundational abstractions for handling HTTP requests and responses. New interfaces define the contract for Controllers, Middleware, Validators, and Kafka handlers, while a dedicated \HttpResponse\ module standardizes status codes and error formatting. To bridge these abstractions with the web server, Express-specific adapters (\ExpressMiddlewareAdapter\ and \ExpressRouteAdapter\) are introduced, translating Express request objects into the domain's internal format and mapping internal response types back to HTTP responses.
src/core/infra · high confidence
Kafka integration handlers for contact lifecycle management
Added factory functions in the Kafka infrastructure layer to wire up handlers for contact subscription, unsubscription, deletion, and information updates, as well as tag title updates. These factories instantiate the necessary Prisma repositories and use cases to process incoming Kafka events for managing contact states and associated metadata.
src/infra/kafka/factories · high confidence
New Kafka handlers for contact and team lifecycle events
Added Kafka message handlers to process contact and team synchronization events. The system now supports subscribing and unsubscribing contacts to teams, updating contact information (name and email), deleting contacts, and updating team titles. Each handler bridges Kafka messages to the corresponding subscription use cases, ensuring that external integration events are correctly reflected in the local database.
src/infra/kafka/handlers · high confidence
New validation infrastructure with field comparison and composition support
The validation layer now includes a CompareFieldsValidator that ensures two specified fields in a request match, alongside the existing RequiredFieldsValidator for checking mandatory parameters. These validators can be combined using a new ValidatorCompositor, allowing multiple validation rules to be applied sequentially to a single input. The change also introduces specific error types, InvalidParamError and MissingParamError, to provide clear feedback on validation failures.
src/infra/validation · high confidence
Queue worker implementation for message delivery
The queue worker infrastructure now initializes the processing pipeline by configuring environment variables via dotenv-flow, instantiating the Amazon SES mail provider and the Bull queue provider, and registering a job processor that executes the DeliverMessageToRecipient use case for incoming queue data.
src/infra/queue · high confidence
Register email delivery events from AWS SNS notifications
The broadcasting module now processes AWS SNS notifications to record email events (delivery, bounce, rejection, complaint, click, and open) for specific recipients. The new RegisterEvent use case and controller validate incoming messages by requiring contact and message IDs, map AWS event types to internal equivalents, and persist the data. For hard bounces, the system automatically marks the associated contact as bounced. Additionally, the controller filters out false-positive open events generated by GMail's proxy and extracts relevant metadata (such as IP address, user agent, or bounce diagnostics) depending on the event type.
src/modules/broadcasting/useCases/RegisterEvent · high confidence
Sender repository interface and implementations for search and management
The senders module now includes a repository layer that defines how sender data is persisted and retrieved. This introduces an \ISendersRepository\ interface along with concrete implementations for in-memory testing (\InMemorySendersRepository\) and production use via Prisma (\PrismaSendersRepository\). These repositories support finding all senders, retrieving a specific sender by ID, identifying the default sender, and performing case-insensitive searches with pagination and total count. The Prisma implementation specifically handles database queries for creating, updating, and deleting senders, as well as searching by name or email.
src/modules/senders/repositories · high confidence
Subscribe contact to tag capability
Users can now associate a contact with a specific tag via a new POST endpoint at /tags/{tagId}/subscribers. The implementation includes the use case, controller, and error handling (InvalidContactError, InvalidTagError), along with unit and end-to-end tests to verify that subscriptions are correctly created in the database and that appropriate errors are returned for non-existent contacts or tags.
src/modules/subscriptions/useCases/SubscribeContactToTag · high confidence
Support for subscribing contacts from external integrations
Added a new use case that allows contacts and tags to be subscribed via external integration IDs. The implementation handles creating new contacts or tags if they do not already exist, looks up existing entities by integration ID or email, and ensures that duplicate subscriptions are not created if a contact is already subscribed to a specific tag.
src/modules/subscriptions/useCases/SubscribeContactFromIntegration · high confidence
Unsubscribe contact from integration use case
Added a new use case that allows unsubscribing a contact from specific integration tags. The implementation locates a contact by its integration ID, finds the corresponding tags, removes the associated subscriptions, and persists the updated contact state. It also includes a specific error handling for cases where the contact is not found.
src/modules/subscriptions/useCases/UnsubscribeContactFromIntegration · high confidence
Unsubscribe contact from tag capability
Users can now remove a contact from a specific tag via a new DELETE endpoint at \/tags/{tagId}/subscribers/{contactId}\. The implementation validates that both the contact and the tag exist and that a subscription relationship is present before removing the association, returning appropriate errors for invalid contacts, tags, or non-existent subscriptions.
src/modules/subscriptions/useCases/UnsubscribeContactFromTag · high confidence
Upsert contact records from integration events
The UpdateContactFromIntegration use case now supports upserting contact information received via Kafka integration events. When processing an update, the system checks if a contact with the given integration ID exists; if it does, the contact's name and email are updated, and if it does not, a new contact is created with the provided details. This ensures that contact data is consistently maintained regardless of whether the contact record already exists in the system.
src/modules/subscriptions/useCases/UpdateContactFromIntegration · high confidence
User authentication via email and password
Users can now authenticate by providing their email and password, which returns a JWT token upon success. The implementation includes the core use case logic, a controller to handle HTTP requests, and corresponding unit and end-to-end tests to verify valid and invalid credential scenarios.
src/modules/accounts/useCases/AuthenticateUser · high confidence
User registration capability added
This change introduces the ability to register new users via a POST /users endpoint. The implementation includes a RegisterUser use case that validates input (name, email, password) and ensures the email is unique, returning specific errors for invalid data or existing accounts. A corresponding controller handles HTTP requests, performing validation and mapping use case results to appropriate HTTP responses (201 Created, 400 Bad Request, 409 Conflict). Tests cover both unit logic and end-to-end API behavior, including authentication requirements for the endpoint.
src/modules/accounts/useCases/RegisterUser · high confidence
Architecture
Defined repository interfaces for broadcasting domain entities
Established the contract layer for the broadcasting module by introducing five new repository interfaces: IEventsRepository, IMessageTagsRepository, IMessagesRepository, IRecipientsRepository, and ITemplatesRepository. These interfaces define the data access methods for their respective domain entities, including operations for creating, saving, finding by ID, searching with pagination (supporting totalCount), and retrieving statistics or details, thereby structuring the persistence abstraction for messages, templates, recipients, tags, and events.
src/modules/broadcasting/repositories · high confidence
Behavioural changes
Add domain-specific error classes for validation failures
New error classes have been introduced to provide specific, user-friendly messages for validation failures across multiple modules. The accounts module now includes InvalidEmailOrPasswordError for authentication issues and AccountAlreadyExistsError for duplicate registration attempts. The broadcasting module adds InvalidContentError and InvalidTitleLengthError to enforce template content and title length constraints. Additionally, the subscriptions module introduces InvalidEmailError and InvalidNameError to handle contact data validation. These changes ensure that users receive clear, contextual feedback when their input does not meet domain requirements.
(repo-wide) · high confidence
Database schema evolution for messaging and contact management
The database schema has been significantly expanded and refined to support a full messaging workflow. Initial tables for users, templates, tags, contacts, messages, events, and recipients were established, followed by a standardization of timestamp columns to snake\_case and the introduction of a dedicated 'senders' table linked to messages. The schema now supports contact segmentation via a 'subscriptions' table (replacing the previous many-to-many tag link), tracks message delivery status through specific event types (Deliver, Open, Click, Bounce, Complaint, Reject), and enforces data integrity with unique constraints on recipients and subscriptions. Additionally, new fields have been added to track sender validation and default status, contact unsubscribe and block states, bounce information, and message recipient counts.
prisma/migrations · high confidence
Introduction of functional Either type and removal of legacy server script
The codebase now includes a functional \Either\ type (\src/core/logic/Either.ts\) providing \Left\ and \Right\ classes to handle success and failure cases explicitly, replacing implicit error handling patterns. Concurrently, the legacy \src/server.ts\ script, which previously used Prisma to directly query users, has been removed, indicating a shift away from ad-hoc database scripts in favor of the new domain logic structure.
src · high confidence
Redis connection now supports password authentication
The Redis infrastructure layer has been updated to allow password-based authentication. The connection configuration now checks for the REDIS\_PASS environment variable and, if present, applies it to the ioredis client options, enabling secure connections to Redis instances that require credentials.
src/infra/redis · high confidence
Tag title validation enforces a 3-to-250 character length constraint
The Tag domain now validates that tag titles are between 3 and 250 characters long. Titles shorter than 3 characters or longer than 250 characters are rejected during creation, ensuring data integrity for tag names within the subscription module.
src/modules/subscriptions/domain/tag · high confidence
Tag title validation updated to allow 3-character minimum
The system now accepts tag titles with a minimum length of 3 characters, relaxing the previous constraint. This change is implemented via a new InvalidTitleLengthError class that explicitly defines the valid range as 3 to 250 characters, ensuring users can create shorter tag names than before.
src/modules/subscriptions/domain/tag/errors · high confidence
Test coverage
Added test factories for Contact, Subscription, and User entities
New test helper factories have been added to the test suite to simplify the creation of test data for Contact, Subscription, and User domain entities. The ContactFactory allows creating contacts with optional overrides for name, email, and subscription status. The SubscriptionFactory facilitates creating subscriptions linked to contacts and tags. The UserFactory provides utilities for creating users with custom credentials and includes a helper to create and authenticate a user by generating a JWT token.
src/test · high confidence
Dependencies
Major dependency overhaul and build system migration
The project has undergone a significant dependency update, migrating Prisma from version 2 to 3 and upgrading core libraries including AWS SDK, BullMQ, ioredis, Nodemailer, and TypeScript. The build toolchain has shifted from using ts-node-dev for development to a Babel-based compilation pipeline for production, introducing several new Babel packages and ESLint plugins while removing the legacy @prisma/cli dependency.
(dependencies) · high confidence
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
How this codebase got here
Baseline
- First survey — no prior run to compare against. CAI 41.
Lenses
- Code Health 68
- Architecture 80
- Maturity 34
- Readiness 45
- Security 39
- Domain Modelling 51
- Performance 85
Changes since last survey
- 243 commits — 198 feature/other, 45 fixes
By area
- src/modules — 86 commits
- (root) — 84 commits
- src/infra — 29 commits
- .github/workflows — 23 commits
- src/domain — 10 commits
- scripts/server.sh — 3 commits
- prisma/migrations — 2 commits
- (repo) — 1 commit
- .plop/templates — 1 commit
- prisma/schema.prisma — 1 commit
- scripts/kafka.sh — 1 commit
- scripts/webhook.sh — 1 commit
- src/config — 1 commit
Notable commits
- fix: Fix tests
- fix: fix(deps): update dependency aws-sdk to v2.834.0
- fix: fix(deps): update dependency aws-sdk to v2.956.0
- fix: fix(deps): update dependency aws-sdk to v2.978.0
- fix: fix(deps): update dependency bullmq to v1.40.0
- fix: fix(deps): update dependency bullmq to v1.40.1
- fix: fix(deps): update dependency bullmq to v1.40.4
- fix: fix(deps): update dependency ioredis to v4.27.7
- fix: fix(deps): update dependency ioredis to v4.27.8
- fix: fix(deps): update dependency ioredis to v4.27.9
- fix: fix(deps): update dependency ioredis to v4.28.0
- fix: fix(deps): update dependency nodemailer to v6.6.3
- fix: fix(deps): update dependency nodemailer to v6.7.0
- fix: fix(deps): update prisma monorepo to v2.29.1
- fix: fix(deps): update prisma monorepo to v2.30.0
- fix: fix(deps): update prisma monorepo to v3
- fix: fix: Add contactsRepository to RegisterEvent factory
- fix: fix: Add execute permission to server.sh
- fix: fix: Add is_validated column to mapper
- fix: fix: Add prisma generate to server startup
- …and 223 more
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
Survey your own repository
diego3g/umbriel was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.
About this page
- The score is its most recent published measurement, taken on 7 October 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
- Measured at commit 9e6195e51a4333f5cfed3bf1442d3c8586329393 — the exact code this score is about.
- Scored under rubric-2026.10.1 — the same rubric and the same method as every other entry in this index.
- Measured by watchdog.canine.dev using codehealth-analyzer preprod-8d8088103122.