Skip to content

Add AdjustBalanceModal and implement Gmail expense review flow - #283

Merged
ali-ahnaf merged 7 commits into
mainfrom
develop
Jul 24, 2026
Merged

Add AdjustBalanceModal and implement Gmail expense review flow#283
ali-ahnaf merged 7 commits into
mainfrom
develop

Conversation

@ali-ahnaf

@ali-ahnaf ali-ahnaf commented Jul 24, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features
    • Added OpenRouter AI settings for securely managing an API key and selecting a model.
    • Added Gmail pending-expense review, including email previews, AI parsing, confirmation, and dismissal.
    • Added balance adjustment controls from the dashboard.
    • AI parsing now runs in the browser using user-provided credentials.
  • Changes
    • Gmail alerts are queued for review instead of automatically creating transactions.
    • Wizard insights continue using local transaction and vault data.
  • Documentation
    • Updated setup, security, Gmail import, project structure, and contributor documentation.
  • Tests
    • Added coverage for pending expenses, AI credentials, and balance adjustments.

@ali-ahnaf
ali-ahnaf merged commit 19647e9 into main Jul 24, 2026
4 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

Greetings, @ali-ahnaf. Thy scroll hath arrived unblemished — the runes align and no conflict bars the path. The council shall now convene over its contents, weighing each incantation by candlelight. Tarry a while, brave adventurer; we shall investigate and return to thee with our verdict.

@github-actions

Copy link
Copy Markdown
Contributor

The quest is sealed, @ali-ahnaf! Thy incantations have been woven into the main path. The realm grows stronger for thy contribution — accept the gratitude of this humble keeper of the codex. May thy commits forever merge cleanly, brave adventurer 💰

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: e8db0c95-dc96-437e-ba15-365eeb41e006

📥 Commits

Reviewing files that changed from the base of the PR and between c3e300b and c930e9f.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (76)
  • README.md
  • documentation/ai-watcher-plan.md
  • documentation/multi-watcher-plan.md
  • packages/api/.env.example
  • packages/api/package.json
  • packages/api/src/data-source.ts
  • packages/api/src/entities/PendingGmailExpense.entity.ts
  • packages/api/src/entities/UserAiCredential.entity.ts
  • packages/api/src/entities/VaultGmailWatcher.entity.ts
  • packages/api/src/index.ts
  • packages/api/src/migrations/1784875736698-AddUserAiCredentials.ts
  • packages/api/src/migrations/1784885759673-AddPendingGmailExpenses.ts
  • packages/api/src/repositories/index.ts
  • packages/api/src/repositories/pending-gmail-expense.repository.ts
  • packages/api/src/repositories/user-ai-credential.repository.ts
  • packages/api/src/routes/ai-credentials.routes.ts
  • packages/api/src/routes/ai-credentials/get-ai-credentials.route.ts
  • packages/api/src/routes/ai-credentials/put-ai-credentials-model.route.ts
  • packages/api/src/routes/ai-credentials/put-ai-credentials.route.ts
  • packages/api/src/routes/pending-expenses.routes.ts
  • packages/api/src/routes/pending-expenses/delete-pending-expense.route.ts
  • packages/api/src/routes/pending-expenses/get-pending-expense-email.route.ts
  • packages/api/src/routes/pending-expenses/get-pending-expenses.route.ts
  • packages/api/src/routes/prompt.routes.ts
  • packages/api/src/routes/prompt/get-usage.route.ts
  • packages/api/src/routes/prompt/post-prompt.route.ts
  • packages/api/src/routes/transactions/post-transaction.route.ts
  • packages/api/src/routes/vault-watchers.routes.ts
  • packages/api/src/routes/vault-watchers/test-extract.route.ts
  • packages/api/src/routes/wizard.routes.ts
  • packages/api/src/routes/wizard/post-chat.route.ts
  • packages/api/src/services/gmail-ai-extractor.service.ts
  • packages/api/src/services/gmail.service.ts
  • packages/api/src/services/index.ts
  • packages/api/src/services/pending-gmail-expense.service.ts
  • packages/api/src/services/prompt.service.ts
  • packages/api/src/services/user-ai-credential.service.ts
  • packages/api/src/services/wizard.service.ts
  • packages/api/src/tests/gmail-ai-extractor.service.test.ts
  • packages/api/src/tests/gmail.service.test.ts
  • packages/api/src/tests/pending-gmail-expense.service.test.ts
  • packages/api/src/tests/prompt.service.test.ts
  • packages/api/src/tests/user-ai-credential.service.test.ts
  • packages/api/src/tests/wizard.service.test.ts
  • packages/shared/src/contracts/ai-credentials.ts
  • packages/shared/src/contracts/ai.ts
  • packages/shared/src/contracts/index.ts
  • packages/shared/src/contracts/pending-expenses.ts
  • packages/shared/src/contracts/wizard.ts
  • packages/ui/src/app/change-password/page.tsx
  • packages/ui/src/app/page.tsx
  • packages/ui/src/app/settings/ai/ModelPicker.tsx
  • packages/ui/src/app/settings/ai/page.tsx
  • packages/ui/src/app/settings/google-oauth/TestExtractModal.tsx
  • packages/ui/src/app/settings/page.tsx
  • packages/ui/src/app/signin/page.tsx
  • packages/ui/src/app/signup/page.tsx
  • packages/ui/src/app/stats/page.tsx
  • packages/ui/src/components/AdjustBalanceModal.test.tsx
  • packages/ui/src/components/AdjustBalanceModal.tsx
  • packages/ui/src/components/LogResourceModal.test.tsx
  • packages/ui/src/components/LogResourceModal.tsx
  • packages/ui/src/components/index.ts
  • packages/ui/src/components/pending-expenses/PendingExpenseDetailModal.tsx
  • packages/ui/src/components/pending-expenses/PendingExpensesPanel.tsx
  • packages/ui/src/components/wizard/WizardChatSheet.tsx
  • packages/ui/src/hooks/useDekSession.ts
  • packages/ui/src/lib/ai/gmail-extractor.ts
  • packages/ui/src/lib/ai/openrouter.ts
  • packages/ui/src/lib/ai/wizard.ts
  • packages/ui/src/lib/api/ProfileApi.ts
  • packages/ui/src/lib/api/WizardApi.ts
  • packages/ui/src/lib/api/index.ts
  • packages/ui/src/lib/crypto/ai-key.ts
  • packages/ui/src/lib/crypto/dek-login.ts
  • packages/ui/src/lib/crypto/dek-session.ts

📝 Walkthrough

Walkthrough

This PR migrates AI-powered transaction parsing from server-side OpenAI services to client-side OpenRouter usage with per-user, E2E-encrypted API keys. It introduces a pending Gmail expense review queue replacing server-side AI extraction, adds a dashboard balance-adjustment feature, removes prompt/wizard server routes, and updates documentation.

Changes

OpenRouter AI Migration and Pending Expense Queue

Layer / File(s) Summary
Shared contracts
packages/shared/src/contracts/ai-credentials.ts, ai.ts, index.ts, pending-expenses.ts, wizard.ts
Adds AI credential/pending-expense DTOs and input types; removes prior usage/wizard chat contracts.
Entities and migrations
packages/api/src/entities/UserAiCredential.entity.ts, PendingGmailExpense.entity.ts, VaultGmailWatcher.entity.ts, data-source.ts, migrations/*
Adds UserAiCredential and PendingGmailExpense TypeORM entities and their migrations; registers them in the data source.
Repositories and services
packages/api/src/repositories/user-ai-credential.repository.ts, pending-gmail-expense.repository.ts, index.ts, services/user-ai-credential.service.ts, pending-gmail-expense.service.ts, services/index.ts, tests/*
Adds repository/service logic for credential status/upsert/model-update and pending-expense list/getEmail/resolve/enqueue, with new unit tests.
Routes and Gmail service wiring
packages/api/src/routes/ai-credentials*, pending-expenses*, index.ts, services/gmail.service.ts, removed prompt.routes.ts, wizard.routes.ts, gmail-ai-extractor.service.ts, .env.example, package.json, tests/gmail.service.test.ts
Adds AI-credential/pending-expense endpoints; removes prompt/wizard/test-extract routes and OpenAI dependency; Gmail message handling now enqueues pending expenses instead of creating transactions via AI extraction.
Browser crypto and DEK session
packages/ui/src/lib/crypto/ai-key.ts, dek-session.ts, dek-login.ts, hooks/useDekSession.ts, app/signin/page.tsx, signup/page.tsx, change-password/page.tsx
Adds WebCrypto DEK/KEK wrap/unwrap and key encrypt/decrypt utilities, a session singleton, and a login-time setup helper wired into sign-in/sign-up.
OpenRouter client and AI feature ports
packages/ui/src/lib/ai/openrouter.ts, gmail-extractor.ts, wizard.ts
Adds browser OpenRouter chat/listModels client, a client-side Gmail transaction extractor, and a client-side wizard response builder.
Profile API client
packages/ui/src/lib/api/ProfileApi.ts, index.ts, removed WizardApi.ts
Replaces server prompt/usage/testExtract endpoints with AI-credential and pending-expense API methods; removes WizardApi.
AI settings UI
packages/ui/src/app/settings/ai/page.tsx, ModelPicker.tsx, settings/page.tsx
Adds a settings page to save an encrypted OpenRouter key and select a model, plus a curated model picker component and navigation entry.
Consumer UI updates
packages/ui/src/app/settings/google-oauth/TestExtractModal.tsx, components/LogResourceModal.tsx, LogResourceModal.test.tsx, components/wizard/WizardChatSheet.tsx, app/stats/page.tsx
Reworks test-extraction, prompt parsing, and wizard chat to run client-side using the decrypted OpenRouter key; removes server token-usage UI.
Pending expenses dashboard panel
packages/ui/src/components/pending-expenses/PendingExpensesPanel.tsx, PendingExpenseDetailModal.tsx, components/index.ts, app/page.tsx
Adds a dashboard panel and detail modal listing pending Gmail expenses with parse/dismiss actions.

Net Yield Balance Adjustment

Layer / File(s) Summary
AdjustBalanceModal and dashboard wiring
packages/ui/src/components/AdjustBalanceModal.tsx, AdjustBalanceModal.test.tsx, app/page.tsx
Adds a modal to create adjustment transactions when a single vault is selected, triggered from a clickable Net Yield value with toast validation.

Documentation Updates

Layer / File(s) Summary
README and planning docs
README.md, documentation/ai-watcher-plan.md, documentation/multi-watcher-plan.md
Updates README encryption/setup/contributor content and removes obsolete watcher planning documents.

Estimated code review effort: 4 (Complex) | ~75 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant AiSettingsPage
  participant DekSession
  participant OpenRouterAPI
  participant ProfileApi
  participant PendingExpenseDetailModal

  User->>AiSettingsPage: enter OpenRouter API key
  AiSettingsPage->>DekSession: get unlocked DEK
  AiSettingsPage->>AiSettingsPage: encryptKey(apiKey, DEK)
  AiSettingsPage->>ProfileApi: setAiCredential(userId, encrypted payload)
  ProfileApi-->>AiSettingsPage: AiCredentialStatusDto

  User->>PendingExpenseDetailModal: click "Parse With AI"
  PendingExpenseDetailModal->>ProfileApi: getAiCredentialStatus(userId)
  PendingExpenseDetailModal->>DekSession: decryptKey(keyCiphertext, keyIv, DEK)
  PendingExpenseDetailModal->>OpenRouterAPI: extractTransactionFromEmail(email, tags)
  OpenRouterAPI-->>PendingExpenseDetailModal: ParsedEmailDto or null
  PendingExpenseDetailModal->>ProfileApi: createTransaction(parsed)
  PendingExpenseDetailModal->>ProfileApi: deletePendingExpense(id)
Loading
sequenceDiagram
  participant GmailPushMessage
  participant GmailService
  participant PendingGmailExpenseService
  participant PushService
  participant Dashboard

  GmailPushMessage->>GmailService: handleMessage(watcherMatch)
  GmailService->>PendingGmailExpenseService: enqueue(userId, gmailMessageId, vaultId, guidanceHint)
  GmailService->>PushService: send "Pending expense to review"
  PushService-->>Dashboard: notification
  Dashboard->>PendingGmailExpenseService: list(userId)
  PendingGmailExpenseService-->>Dashboard: PendingGmailExpenseDto[]
Loading

Possibly related issues

Possibly related PRs

  • ali-ahnaf/pocket_pixel#270: Both add AdjustBalanceModal.tsx and its tests, integrated into the dashboard "Net Yield" click flow.
  • ali-ahnaf/pocket_pixel#282: Both implement the same OpenRouter migration with E2E-encrypted AI credentials, DEK session/crypto utilities, and pending-expense review queue changes.
  • ali-ahnaf/pocket_pixel#273: Both rework the Gmail watcher/email parsing pipeline around guidanceHint and GmailService handling for AI extraction.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch develop

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants