Remove application-level CORS and IP whitelisting as security is now handled at CloudFlare edge. CORS is not applicable for backend webhook service, and IP whitelisting is more effectively managed at infrastructure layer. Also translate Dockerfile comments to English and add registry URL to build script.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add Delivered status to BillsNotificationStatus enum
- Add Delivered status to RentNotificationStatus enum
- Update JSDoc comments for clarity
- Delivered status will be set by webhook when email is confirmed delivered
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Remove unused MailgunMessageData type import
- Remove type annotations for messageData
- Resolves TypeScript compilation error in email-worker
The mailgun.js package doesn't properly expose Types module,
and the type annotation wasn't necessary since mailgunClient
is already typed as any.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Rename billFwd* to billsNotification* for clarity
- Rename rentDueNotification* to rentNotification* for consistency
- Rename utilBillsProofOfPayment to billsProofOfPayment
- Introduce enums for type safety:
- BillsNotificationStrategy (WhenPayed, WhenAttached)
- BillsNotificationStatus (Scheduled, Sent, Failed)
- RentNotificationStatus (Sent, Failed)
- Replace "pending" status with "scheduled" for better semantics
- Fix function names to proper camelCase
- Fix incorrect import path in web-app/app/lib/format.ts
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Remove private registry references and SSH key handling from Docker
build process. Images now build locally without registry prefix.
Changes:
- Remove SSH key copying from Dockerfile (no private npm packages)
- Remove registry.ngit.hr references from build and run scripts
- Simplify image tags to local format (no registry prefix)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implemented a production-ready TypeScript/Express.js service to receive
and log MailGun webhook events (delivered, failed, opened, clicked, etc.).
Key features:
- Webhook endpoint (POST /webhook) with comprehensive event logging
- Full TypeScript type definitions for all MailGun event types
- Prometheus metrics integration for monitoring
- Health check endpoint (GET /ping)
- Comprehensive Jest test suite with 87.76% coverage
- Docker containerization with build scripts
Removed template/example code:
- All SQL/MSSQL dependencies and related code
- Example auth router and middleware
- PRTG metrics support (simplified to Prometheus only)
- Unused middleware (CORS, IP whitelist, request parsing/validation)
- Template documentation (kept only MailGun webhook API spec)
The service is clean, minimal, and focused solely on receiving and
logging MailGun webhook events to the console.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Updated all email templates to include locale prefixes (/en/ or /hr/)
in URLs to ensure language consistency when users click email links.
Changes:
- Email validation templates: /email/verify/ → /{locale}/email/verify/
- Rent due templates: /share/rent-due/ → /{locale}/share/rent-due/
- Bills due templates: /share/bills-due/ → /{locale}/share/bills-due/
- Unsubscribe links: /email/unsubscribe/ → /{locale}/email/unsubscribe/
- Base site links in EN templates: / → /en
Benefits:
- Users land on pages in the same language as their email
- Better UX - no manual language switching needed
- Proper i18n implementation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Created a new /share/rent-due/ page to display rent payment information
separately from utility bills.
Changes:
- Created /share/rent-due/[id]/ page structure with RentViewPage component
- Created ViewRentCard component to display rent amount and payment info
- Added uploadRentProofOfPayment action for tenant proof upload
- Added translation keys for rent-specific labels (en/hr)
- Updated rent email templates to link to /share/rent-due/ instead of /share/bills-due/
- Updated documentation to reflect new URL structure
The rent page displays:
- Rent amount
- IBAN or Revolut payment information with QR/barcode
- Rent proof of payment upload (when enabled)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Update email worker to select templates based on BillingLocation.tenantEmailLanguage:
- Change default language from 'en' to 'hr' in emailTemplates.ts
- Pass language parameter (location.tenantEmailLanguage || 'hr') to all loadAndRender calls
- Applies to email validation, rent due, and utility bills notifications
Email templates are now automatically selected based on tenant's language preference,
defaulting to Croatian when not specified.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add Croatian (hr) translations for all email templates:
- email-validation: email verification request
- rent-due: rent payment due notification
- util-bills-due: utility bills notification
All templates maintain same structure and styling as English versions.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Moved the language selector to appear before the email address field for better
UX flow. Users now select the notification language first, then enter the email
address that will receive notifications in that language.
Also applied right-alignment to the "new email" status indicator for consistency.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added justify-end to email status display to align icons and text to the right
side of the container for better visual hierarchy.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Improved UI organization by moving the language selector into the same fieldset
as the tenant email input, since both are related to email notifications. The
language selector now only appears when email notifications are enabled.
Changes:
- Move language selector inside tenant email fieldset (no separate fieldset)
- Add label for tenant email input field
- Simplify notification language label text
- Remove unused notification-language-legend translation key
- Language selector shares visibility condition with email field
This provides a more logical grouping of related settings and reduces visual
clutter when email notifications are disabled.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added ability to select the language for automatic notification emails sent to
tenants. Users can choose between Croatian (hr) and English (en). If not set,
defaults to the current UI language.
Changes:
- Add tenantEmailLanguage field to BillingLocation type (shared-code)
- Add language selector fieldset in LocationEditForm below email settings
- Add Zod validation for tenantEmailLanguage in locationActions
- Include field in all database insert and update operations
- Default to current locale if not explicitly set
- Add translation labels for language selector (EN/HR)
This allows tenants to receive bills and notifications in their preferred language
regardless of the landlord's UI language preference.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Removed unnecessary loop when checking if bill forwarding should be triggered.
Since we only need to determine if forwarding should happen once per location
(after all bills are updated), we can check with just the first paid bill
instead of looping through all updates.
Benefits:
- More efficient (no redundant checks for unpaid bills)
- Clearer logic (one check per location, not per bill update)
- Avoids confusion about checking bills that weren't marked as paid
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Created shared billForwardingHelpers module to avoid code duplication and
implemented automatic bill forwarding trigger in the multi-bill-edit feature.
Changes:
- Extract shouldUpdateBillFwdStatusWhenAttached and shouldUpdateBillFwdStatusWhenPayed
to new billForwardingHelpers.ts module
- Update billActions.ts to import from shared module instead of local definitions
- Add forwarding logic to monthActions.updateMonth to set billFwdStatus to "pending"
when all tenant bills are marked as paid
This ensures consistent bill forwarding behavior whether updating bills individually
or in bulk via the multi-bill-edit page.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Changed rent amount handling to use whole currency units throughout the application
instead of storing in cents. This simplifies data entry and aligns with Zod validation
requiring integer values.
Changes:
- Set rent input step to "1" (whole numbers only)
- Remove cents-to-currency conversion (/ 100) when formatting for email
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Made toggle labels more explicit by adding "to tenant automatically" to clearly
indicate the recipient and automatic nature of the notifications.
Changes:
- "forward utility bills" → "forward utility bills to tenant automatically"
- "send rent notification" → "send rent notification to tenant automatically"
- Fixed capitalization in Croatian: "obavjest O" → "obavjest o"
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Location Edit Form:
- Add validation requiring user to select update scope when editing locations
- Add "no-scope-selected" as placeholder option that must be replaced with valid choice
- Display validation error if user attempts to submit without selecting scope
- Clarify update scope options with improved wording (e.g., "ALL months (past and future)")
Bill Form UX:
- Add emoji icons (👤 tenant, 🔑 landlord) to "who bears cost" options for visual clarity
Translation updates:
- Add "update-scope-required" validation message (EN/HR)
- Improve clarity of update scope option labels
- Standardize Croatian terminology ("zadani" instead of "trenutni" for current month)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Modified bill forwarding logic to only consider bills marked as "billed to tenant"
when determining if all bills are ready for forwarding. Bills billed to landlord
should not affect the forwarding trigger.
Changes:
- Filter out landlord bills before checking if all bills are paid/attached
- Improved status check to explicitly look for "pending" or "sent" status
- Added edge case handling when no tenant bills exist
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add TypeScript generic type parameters to MongoDB collection calls and
remove ObjectId conversion workaround.
Changes:
- Added <BillingLocation> type parameter to collection().updateOne() calls
- Simplified _id usage by removing new ObjectId() conversion
- Cleaner code with better type inference
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Replace . encoding with zero-width space (​) approach to prevent
email clients from auto-linking "rezije.app" in header and body text.
Changed "rezije.app" to "rezije​.​app" which displays normally
but breaks the auto-link detection pattern.
Applied to:
- Header h1 tags in all templates
- Body text mentions in email-validation template
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Replace the period in "rezije.app" header text with HTML entity . to
prevent email clients from automatically converting it into a clickable link.
This change only affects the display text in the h1 header, not the actual
URLs which remain unchanged for proper functionality.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fix imports in app/lib/actions/ that were still using relative paths
('../db-types') instead of the shared-code package.
Updated files:
- billActions.ts
- emailActions.ts
- locationActions.ts
- monthActions.ts
- navigationActions.ts
- printActions.ts
- userSettingsActions.ts
All imports now correctly reference @evidencija-rezija/shared-code.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Replace inline HTML in email notifications with professional HTML templates
for better email client compatibility and consistent branding.
Changes:
- Created emailTemplates.ts utility for loading and rendering templates
- Template caching for performance
- Variable substitution with ${variable} syntax
- Warning logging for unreplaced variables
- Updated sendVerificationRequests to use email-validation template
- Variables: location.tenantName, ownerName, location.name, shareId
- Updated sendRentDueNotifications to use rent-due template
- Fetches user settings for owner name and currency
- Calculates rent due date from yearMonth and rentDueDay
- Formats rent amount (converts cents to display format)
- Variables: location.tenantName, location.name, rentDueDate,
rentAmount, currency, ownerName, shareId
- Updated sendUtilityBillsNotifications to use util-bills-due template
- Calculates total amount from all bills
- Fetches user settings for owner name and currency
- Variables: location.tenantName, location.name, totalAmount,
currency, ownerName, shareId
- Fixed ObjectId type mismatches in MongoDB operations
All emails now feature:
- Responsive 3-column layout
- rezije.app branding with logo
- Professional typography and spacing
- Unsubscribe links
- Email client compatible table-based layouts
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add the shared-code workspace to VS Code workspace configuration for
better development experience and navigation.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Update web-app to use @evidencija-rezija/shared-code for common types
and utilities instead of maintaining duplicate copies.
Changes:
- Add shared-code dependency to package.json
- Update all imports across 35+ files to use @evidencija-rezija/shared-code
- Remove duplicate db-types.ts and shareChecksum.ts files
This ensures type consistency between web-app and email-worker and
reduces maintenance burden.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Update email-worker to use @evidencija-rezija/shared-code for common types
and utilities instead of maintaining duplicate copies.
Changes:
- Add shared-code dependency to package.json
- Update imports in emailSenders.ts to use shared-code
- Remove duplicate db-types.ts and shareChecksum.ts files
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Create a new shared-code workspace containing common code shared between
web-app and email-worker. This reduces code duplication and ensures
consistency across workspaces.
Structure:
- Root package.json defines workspaces (web-app, email-worker, shared-code)
- shared-code contains db-types.ts and shareChecksum.ts
- Configured as internal npm package (@evidencija-rezija/shared-code)
- No build step required (TypeScript source consumed directly)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Rename email templates to follow a consistent naming pattern with language
suffix for future i18n support:
- email-validation-email.html -> email-template--email-validation--en.html
- rent-due-email.html -> email-template--rent-due--en.html
- utility-bills-due-email.html -> email-template--util-bills-due--en.html
This naming convention allows for easy addition of Croatian (hr) and other
language versions of the same templates.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add three email templates for tenant notifications with consistent branding
and professional design:
1. email-validation-email.html - Email verification request
2. rent-due-email.html - Rent payment due reminder
3. utility-bills-due-email.html - Utility bills ready notification
All templates feature:
- Responsive 3-column layout with center content area
- rezije.app branding with logo and color scheme (#0070F3 blue, #3c3c3d header)
- Email client compatible table-based layouts with inline CSS
- Template variables for dynamic content (tenant name, location, amounts, etc.)
- Unsubscribe links and footer information
- Professional typography and spacing
Templates use ${variable} syntax for server-side replacement.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Update email verification subject line to be more personal and inviting by
including the landlord's name. Also add the property location name to the
email body to provide better context for the recipient.
- Subject changed from "Please verify your e-mail address" to
"{ownerName} has invited you to rezije.app"
- Added location name to email body for clarity
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add explicit EU API endpoint configuration for Mailgun client to ensure emails
are sent through the correct regional API server. This is required for accounts
created in the EU region.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Configure nodemon to automatically load environment variables from .env file
using dotenv/config preload. This ensures all environment variables are available
during development without manual loading.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add a reset button to the email verification failed status display, allowing users
to retry email verification after a failure. The button appears alongside the error
message and icon for easy access.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add English and Croatian translation keys for the verification-failed email status
that were missing from the previous UI implementation commit.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Display verification failed status in location cards and edit forms to provide
clear visual feedback when email verification fails. Uses red X icon and error
styling consistent with other failure states.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Enables automatic email notification trigger when all bills are marked as paid
under "when-payed" forwarding strategy. Complements the existing "when-attached"
strategy to support both notification workflows.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Enables automatic email notification trigger when the last bill receives an
attachment under "when-attached" forwarding strategy. This eliminates manual
intervention for marking locations ready for tenant notification.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add MongoDB connection module for database access
- Implement Mailgun email service for sending notifications
- Add shareChecksum utility for generating secure share links
- Implement three email sender functions:
- Email verification requests (highest priority)
- Rent due notifications (CET timezone)
- Utility bills due notifications
- Create main email worker with budget-based email sending
- Add environment variables for configuration
- Install dependencies: mongodb, mailgun.js, form-data
- Update package.json description to reflect email worker purpose
- Add .env.example with all required configuration
The worker processes emails in priority order and respects a configurable
budget to prevent overwhelming the mail server. All database operations are
atomic and updates are performed immediately after each email send.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>