Support Microsoft-specific user info fields:
- email: check 'mail' and 'userPrincipalName' as fallbacks
- name: check 'displayName' (camelCase) for Microsoft Graph API
Add rate limit environment variables to prevent 429 errors during E2E tests.
Use high limits (1000) matching compose.e2e.yml configuration to allow
rapid sequential requests during test execution.
Remove glob and rimraf from overrides to use versions compatible with nyc@15.
This accepts deprecated warnings for glob@7 and rimraf@3, but ensures
@cypress/code-coverage works correctly for E2E test coverage.
Keep inflight override to eliminate that specific warning.
Add postinstall script that patches nyc/index.js to handle modern versions
of glob and rimraf. These packages now export objects/named exports instead
of functions, which breaks nyc@15's promisify() calls.
This fixes the 'original argument must be of type function' error.
# Conflicts:
# webapp/scripts/patch-nyc.cjs
Add postinstall script that patches nyc@15 fs-promises.js to handle
promisify errors gracefully. This fixes the 'original argument must be
of type function' error when running Cypress E2E tests with coverage.
The @cypress/code-coverage package bundles nyc@15 which is incompatible
with Node.js 22+. Downgrade to Node.js 20 for E2E tests only to maintain
coverage collection while other workflows use Node.js 22.
Add Rollup onwarn handler to filter the known MISSING_EXPORT warning
where vue-i18n accesses internal Vue APIs (currentInstance).
This is a known compatibility issue that doesn't affect runtime behavior.
Use npm overrides to force modern versions:
- glob: v7.2.3 → v10.5.0
- rimraf: v3.0.2 → v5.0.10
- inflight: replaced (no longer needed with glob v10+)
This eliminates all deprecation warnings during npm install.
The go:embed directive in main.go requires web/dist to exist during compilation.
Backend tests don't need the actual frontend, just an empty directory to satisfy the embed directive.
Fix bash arithmetic syntax error when calculating coverage percentages
from LCOV files. The issue occurred when grep results contained whitespace
or when values were empty strings.
Reorganize GitHub Actions workflows into reusable components and implement
complete code coverage tracking across backend, frontend, and E2E tests.
**CI/CD Improvements:**
- Split monolithic ci.yml into 6 specialized reusable workflows
- New workflows: test-backend, test-frontend, test-e2e, build-docker, security, coverage-report
- Orchestrated execution with proper dependencies and parallel jobs
- Codecov integration with multi-flag coverage (backend/frontend/e2e)
**Frontend Testing:**
- Add Vitest for unit testing with coverage-v8 provider
- Create test setup with window mocks for Ackify globals
- Add 34 unit tests for titleExtractor, referenceDetector, and http utils
- Configure Istanbul instrumentation for E2E coverage collection
- Integrate @cypress/code-coverage for E2E test coverage
**Test Infrastructure:**
- Create run-tests-suite.sh for local comprehensive test execution
- Proper Docker Compose orchestration for integration and E2E tests
- Automatic cleanup handlers with trap for test environments
- Coverage summary aggregation across all test types
**Bug Fixes:**
- Fix backend config tests after OAuth/MagicLink validation changes
- Update tests from panic expectations to error checking
- Ensure OAUTH_COOKIE_SECRET is properly configured in tests
**Configuration:**
- Add .codecov.yml for coverage reporting with flags
- Add .nycrc.json for E2E LCOV generation
- Update .gitignore for test artifacts and coverage reports
- Configure Vite for test environment and code instrumentation
Add context.Context parameter to checksum computation functions
to enable request cancellation, timeout propagation, and better
observability for remote document downloads.
Add context.Context parameter to cryptographic signature operations
to enable distributed tracing, timeout propagation, and cancellation
handling throughout the signature creation pipeline.
This is a breaking change for the cryptoSigner interface but
maintains backward compatibility at the API level.
Improve the email retry mechanism by adding 0-30% random jitter
to the exponential backoff calculation. This prevents multiple
failed emails from retrying at exactly the same time, which could
cause load spikes on the SMTP server.
Example retry times (with jitter):
- 1st retry: 1.0-1.3 minutes
- 2nd retry: 2.0-2.6 minutes
- 3rd retry: 4.0-5.2 minutes
Changes:
- Replace fmt.Println with logger.Logger.Warn in config loading
- Remove client_id and auth URLs from OAuth provider logs
- Remove user email, name, and sub from authentication logs
- Use structured logging for worker shutdown errors
- Fix MagicLink status logging (only log when actually enabled)
Backend:
- Add Search() method to DocumentRepository for ILIKE pattern matching on doc_id, title, url, description
- Add Count() method to accurately count total matching documents (used for pagination)
- Update admin handler to support search query parameter with proper pagination
- Implement full public documents API with search support (previously stub)
- Update test mocks to include new repository methods
Frontend:
- Replace client-side filtering with server-side search in admin dashboard
- Add debounced search input (300ms delay) to reduce API calls
- Separate loading states: initial page load vs. search/pagination (prevents input focus loss)
- Add visual feedback: spinning loader icon in search field during active search
- Enable pagination during search (previously disabled)
- Pass search parameter to API service
* feat(mail): add option to skip TLS certificate verification
Add ACKIFY_MAIL_INSECURE_SKIP_VERIFY environment variable to allow
bypassing TLS certificate verification for self-signed certificates.
This is useful for development/testing environments with self-signed
SMTP certificates while maintaining secure defaults (false by default).
* docs: add ACKIFY_MAIL_INSECURE_SKIP_VERIFY documentation
Backend changes:
- Add SMTPEnabled flag to distinguish SMTP service from MagicLink authentication
- Fix URL-encoded email decoding in DELETE /signers/{email} endpoint
- Add detailed error logging for expected signer removal operations
- Initialize ReminderAsync and MagicLink services unconditionally
- Update config tests to reflect new MagicLink requires explicit enabling
Frontend changes:
- Add ACKIFY_SMTP_ENABLED window variable for feature detection
- Hide delete button for expected signers who have already signed
- Show email reminders card only when SMTP enabled or history exists
- Display informative alert when SMTP disabled but reminder history present
- Add i18n translations for email service disabled message (5 languages)
These changes improve admin experience by preventing invalid operations
(deleting signers who signed, sending emails without SMTP) and providing
clear feedback about feature availability.
- Move /logout route outside OAuth-only block to support both OAuth
and MagicLink authentication methods.
- Also fix notification icon alignment in AuthChoicePage.
- And add press-kit inside /docs
Add new configuration option ACKIFY_ONLY_ADMIN_CAN_CREATE (default: false) to control who can create documents.
Backend changes:
- Add OnlyAdminCanCreate config field to AppConfig
- Implement authorization checks in document handlers
- Protect POST /documents and GET /documents/find-or-create endpoints
- Add unit tests for admin-only document creation (4 tests)
Frontend changes:
- Inject ACKIFY_ONLY_ADMIN_CAN_CREATE to window object
- Hide DocumentForm component for non-admin users when enabled
- Add i18n translations (en, fr, es, de, it)
- Display warning message for non-admin users
Documentation:
- Update .env.example files with new variable
- Update configuration docs (en/fr)
- Update install script to prompt for restriction option
- Update install/README.md
When enabled, only users listed in ACKIFY_ADMIN_EMAILS can create new documents. Both direct creation and find-or-create endpoints are protected.
Add authentication tokens embedded in reminder emails allowing users to
authenticate and sign documents in one click.
Changes:
- Add 'purpose' (login/reminder_auth) and 'doc_id' columns to magic_link_tokens
- Implement CreateReminderAuthToken (24h validity) and VerifyReminderAuthToken
- Create reminder auth handler and route (/api/v1/auth/reminder-link/verify)
- Update ReminderService and ReminderAsyncService to generate auth tokens
- Fix table name mismatch: magic_links → magic_link_tokens throughout
- Reorder service initialization in server.go for proper dependencies
Token validity:
- Magic Link: 15 minutes (login)
- Reminder Auth: 24 hours (document signature)
The reminder auth flow:
1. Admin sends reminder
2. User receives email with auth link
3. User clicks link → auto-authenticated if not logged in
4. User redirected to document signature page
5. If already authenticated with correct account, skip auth step
The magic link email is now sent in the same language as the frontend
at the time of the request, matching the behavior of reminder emails.
Changes:
- Modified MagicLinkService.RequestMagicLink to accept locale parameter
- Handler extracts locale using i18n.GetLangFromRequest() from HTTP headers
- Falls back to "en" if locale is empty
- Consistent with reminder email locale detection
- feat(admin): accept URLs, file paths, and IDs in document creation form
- Modified AdminDashboard to use findOrCreateDocument service
- Now matches user UI functionality for flexible document references
- feat(i18n): replace all hardcoded French texts with translation keys
- Added 50+ new translation keys across admin and user interfaces
- Updated 7 Vue components: AdminDashboard, AdminDocumentDetail,
DocumentForm, SignButton, SignatureList, SignaturesPage, EmbedPage
- Synchronized all new keys to 5 languages (fr, en, es, de, it)
- All templates now use vue-i18n with proper parameterized translations
- Zero hardcoded texts remaining in HTML templates
Change test URLs from '/sign?doc=' to '/?doc=' to match the correct
frontend route after the URL path correction in reminder emails.
Updated base64 encoded state in callback test:
- Old: L3NpZ24_ZG9jPXRlc3Q (decodes to /sign?doc=test)
- New: Lz9kb2M9dGVzdA (decodes to /?doc=test)
Change signature URL in reminder emails from '/sign?doc=' to '/?doc='
to match the correct frontend route.
Updated in:
- ReminderService.sendSingleReminder
- ReminderAsyncService.queueSingleReminder
- Email helper tests
Backend changes:
- Use 'else if' to prevent activating both TLS and STARTTLS simultaneously
- Add StartTLSPolicy = MandatoryStartTLS for proper STARTTLS enforcement
- Add comments explaining TLS modes (implicit SSL vs explicit STARTTLS)
Install script changes:
- Auto-detect TLS configuration based on port number
- Port 465 → TLS=true, STARTTLS=false (implicit SSL)
- Port 587 → TLS=false, STARTTLS=true (explicit TLS/STARTTLS)
- Non-standard ports → manual configuration with clear prompts
This fixes timeout errors when sending emails via Gmail SMTP (port 587)
which requires STARTTLS, not direct TLS connection.
- Add ACKIFY_AUTH_OAUTH_ENABLED=true when OAuth is configured
- Add ACKIFY_AUTH_OAUTH_ENABLED=false when OAuth is not configured
- Write ACKIFY_AUTH_MAGICLINK_ENABLED with true/false value explicitly
- Provides clear visibility of enabled authentication methods in .env
These variables are already passed to containers via compose files.