* feat: initial email impl
* feat: IMAP email ingest (builds on the scaffold) (#100)
* chore: add imap-simple, mailparser, vitest
* feat: AES-256-GCM helpers for email credentials
* feat: extract ingestUnsortedFile helper, reuse in upload action
* chore: gitignore .worktrees/
* feat: email-sync types and pure attachment/search filters
* feat: imap-simple + mailparser client wrapper
* feat: email sync orchestration with UID watermark + status persistence
* feat: encrypt email credentials at rest, add UID/addedAt fields
* feat: real IMAP test-connection, scoped sync-now, thin cron entry
* docs: update email app README to match real IMAP/encryption/UID behavior
* fix: nest SINCE search criteria and guard missing addedAt for first-run sync
* fix: show last-sync time and error detail from sync in server card
* fix: skip storage recompute when no attachments ingested
Avoids an ENOENT crash on first sync when the user's uploads dir does not exist yet and nothing was ingested; this was also masking the real per-server error. Adds regression tests for the guard.
* feat: configurable initial-grab window (fetch-since date)
First sync is bounded by a user-chosen 'Fetch emails since' date instead of the server's addedAt; blank = entire mailbox (IMAP ALL). The UID watermark takes over after the first run.
* fix: add missing @langchain/core dependency
@langchain/core is only a peer dep of the @langchain/* packages and was not installed on a clean npm install, breaking the build (e.g. /unsorted via ai/analyze).
* fix: harden email sync — UID dedup guard, locked status write, graceful decrypt, scrypt memo
Addresses review findings: skip messages at/below the UID watermark (defends against the IMAP `n:*` re-fetch quirk); lock the app_data row with SELECT FOR UPDATE so concurrent cron/manual syncs can't clobber each other; return a friendly error when a stored password can't be decrypted (e.g. after BETTER_AUTH_SECRET rotation) and document the coupling; memoize the scrypt-derived key.
* feat: enforce per-server syncInterval on cron; skip non-Buffer attachments
The cron now honors each server's syncInterval (manual Sync Now bypasses the throttle), so the configured interval is no longer ignored. Attachments whose parsed content is not a Buffer are skipped instead of throwing on .length. Adds throttle regression tests.
* refactor: remove dead lastProcessedMessageId field; clarify cron throttle in README
lastProcessedMessageId was superseded by the lastProcessedUid watermark and never read; dropped from the type and form state. README now describes the per-server interval as an app-level throttle (manual Sync Now bypasses).
* feat(email): UI-selectable sync frequency + working cron heartbeat
Replace the per-server sync-interval number input with a dropdown of
presets (15m/30m/hourly/6h/12h/daily). Switch the stored unit from hours
to minutes and update the throttle accordingly.
Make the cron actually run: heartbeat now fires every 5 minutes as the
resolution floor while each mailbox's UI frequency gates real fetches.
Propagate env into cron jobs via /etc/cron.env (cron strips the
environment) and add BETTER_AUTH_SECRET to the email-sync service in the
dev/build compose files so stored passwords can be decrypted.
* fix(email): reset Add Server dialog to provider selection on close
Radix's onOpenChange only toggled isOpen, so closing the dialog via Esc,
overlay click, or the X left the step/selectedProvider state intact.
Reopening then jumped straight to the previous provider's config form
instead of the provider-selection screen. Route every close through
handleClose() to reset the step.
---------
Co-authored-by: Evgenii Burmakin <Freika@users.noreply.github.com>
* feat: add transaction deduplication with side-by-side comparison modal
* feat: implement three-way duplicate resolution logic
- Add Row-Level check (Merchant/Total/Currency/Date) to Transaction model.
- Implement side-by-side comparison modal with Older/Newer/Both options.
- Update AI and CSV workflows to intercept duplicates.
Closes#92
* fix: include currency code and fallback in transaction deduplication check
Closes#92
* refactor(transactions): separate deduplication logic from creation model
- Extracted duplicate checking into a dedicated `findDuplicateTransaction` method in `models/transactions.ts`
- Restored `createTransaction` to a pure, atomic database insertion to remove unexpected side effects
- Updated all server actions (createTransactionAction, saveInvoice, saveFile, saveTransactions) to orchestrate the duplication check before calling the creation model
Addresses reviewer feedback to separate concerns and maintain clean model methods.
Support Ollama, LM Studio, vLLM, and any OpenAI-compatible API
via a configurable base URL. Reuses ChatOpenAI with custom baseURL,
no new dependencies. Local models use direct JSON parsing instead
of withStructuredOutput since many don't support function calling.
Co-authored-by: FasterOP <7832832+mmplisskin@useres.noreply.github.com>
Removes the generateId: false setting from Better Auth config that was causing UUID generation errors when creating OTP verification records.
According to Better Auth documentation, generateId: false should only be used for auto-increment ID schemas. For UUID-based schemas, Better Auth should generate UUIDs using crypto.randomUUID().
This fixes the 'Failed to send the code' error during OTP email verification.
- Add calcNetTotalPerCurrency function to calculate signed totals (income positive, expenses negative)
- Update transaction list footer to display both net total and turnover
- Use semantic HTML markup (<dl>, <dt>, <dd>) for better accessibility
- Add color coding: green for positive net, red for negative net
- Maintain turnover calculation for total transaction volume
Fixes issue where transaction totals did not respect transaction type (income/expense)
* feat: add google provider
* fix: default for google model
* feat: multiple providers
* fix: defaults from env for login form
* fix: add mistral to env files
* chore: delete unused code
* chore: revert database url to original
* fix: render default value for api key from env on server
* fix: type errors during compilation
---------
Co-authored-by: Vasily Zubarev <me@vas3k.ru>