- Bump mailgun-webhook-service version from 1.0.0 to 1.0.1
- Add mailgun-webhook to root workspace in package-lock.json
- Update all lockfiles to reflect workspace changes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Security Improvements:
- Add HMAC-SHA256 signature verification for MailGun webhooks
- Remove hardcoded signing key fallback, require env variable
- Add proper payload structure validation before processing
API Changes:
- New types: MailgunWebhookPayload, MailgunWebhookPayloadSignature
- New type guard: isMailgunWebhookPayload()
- Returns 401 for invalid signatures, 400 for malformed payloads
Configuration:
- Add MAILGUN_WEBHOOK_SIGNING_KEY to both docker-compose files
- Service fails fast on startup if signing key not configured
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Change from webhook.rezije.app to mailgun-webhook.rezije.app for clarity
- Update both standalone and swarm configurations
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add mailgun-webhook service to both standalone and swarm deployments
- Configure service with Prometheus monitoring and debug logging
- Route traffic through Traefik at webhook.rezije.app
- Use version-controlled image with MAILGUN_WEBHOOK_VERSION variable
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Upgrade email-worker from Node 18 to Node 20
- Update distroless images to nodejs20-debian12:nonroot for both services
- Improves security by running containers as nonroot user
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add ci-build-docker-image.sh script to automate Docker image builds in CI/CD pipelines. Script iterates through configured workspaces and builds images using --auto-version and --auto-push flags. Currently configured for mailgun-webhook, easily extensible for additional workspaces.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add --auto-version flag to automatically use version from package.json and check if image already exists in registry before building. If image exists, script exits to prevent duplicate versions. Rename --autopush to --auto-push for consistent flag naming.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add optional --autopush parameter to skip the interactive push prompt and automatically push built images to registry. Useful for CI/CD pipelines and automated builds.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
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>