* feat: add read/write scopes to API keys
API keys now require explicit scopes (e.g. transactions:read,
invoices:write) instead of having implicit full access. The create
dialog shows grouped checkboxes per domain with read/write split.
Legacy keys with null scopes default to read-only. MCP tools/list
is filtered by scope and tools/call rejects unauthorized calls.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Enhance API key scopes with suppliers and update descriptions for better clarity
* fix: drop function before recreating with changed return type
PostgreSQL cannot change return type via CREATE OR REPLACE.
Drop the existing function first to avoid SQLSTATE 42P13.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: add new migration to drop and recreate function with scopes return type
The original migration was already applied, so a new migration is needed
to DROP the function first before recreating with the updated return type.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: add DROP FUNCTION to original migration, remove redundant fix migration
Preview branches replay all migrations from scratch. The original migration
must DROP the function before recreating it with a changed return type,
otherwise PostgreSQL rejects the CREATE OR REPLACE. The separate fix
migration is no longer needed.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: rename migration to avoid duplicate version in schema_migrations
Version 20260325120000 is already recorded in the preview DB from a
prior failed apply. Renaming to 20260326130000 so Supabase treats it
as a new migration.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: event log, pending operations, and MCP staging
- Event log system: persist bus events to event_log table for external
automation platforms. Batch insert for transaction.synced. Daily
cleanup cron at 02:00 UTC.
- Pending operations: MCP write tools (categorize, create customer,
create invoice) now stage to pending_operations instead of executing
directly. Users review and commit/reject from /pending in the web UI.
- Granskning page: card-based review UI with expandable previews,
commit/reject dialogs. Only shown in nav when pending ops exist.
- Commit route re-executes using core lib functions (no extension
imports). Guards against stale state (double-commit, deleted entities).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: stage new MCP write tools after main merge
Add staging for 4 new write tools from #133:
- mark_invoice_paid, send_invoice, mark_invoice_sent,
match_transaction_invoice
- Expand pending_operations CHECK constraint
- Add commit executors with full execution logic
- Add UI labels and generic preview component
- Remove confirm parameter from categorize (single-call staging)
- Fix UUID in pending op title (fetch transaction description)
- Hide Granskning nav when no pending ops
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address PR review feedback
- Fix TS build error: use `select('*, customer:customers(*)')` for
match_transaction_invoice to avoid array type inference
- Add status guard to commitSendInvoice (prevents duplicate sends)
- Replace auth.admin.getUserById with user email from session auth
- Restore optimistic lock check in commitMatchTransactionInvoice
- Fix tool description typo: expense_software → expense_office
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: remove gnubok_categorize_with_receipt tool
The tool requires Claude to generate the entire base64-encoded file as
tool arguments token-by-token, which is extremely slow for large PDFs.
Receipt attachment should happen via the widget (where JavaScript
handles encoding) or through the web app.
The receipt matcher widget and gnubok_receipt_matcher tool remain —
they provide the intended UX for matching receipts to transactions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: update widget to call gnubok_categorize_transaction
The widget was still calling the removed gnubok_categorize_with_receipt
tool. Updated to call gnubok_categorize_transaction instead (text-only,
no file upload). Receipt attachment via the widget is deferred to a
future iteration.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add MCP Apps receipt matcher widget for inline receipt-to-transaction matching
Adds an interactive HTML widget that renders inline in Claude Desktop via MCP Apps
(SEP-1865), letting users drag receipts onto uncategorized transactions to categorize,
book, and attach documents in one flow without leaving the conversation.
- Extract categorizeTransactionCore() shared by both categorization tools
- Add gnubok_receipt_matcher tool with _meta.ui for MCP Apps widget rendering
- Add gnubok_categorize_with_receipt tool (categorize + upload document)
- Add resources/list and resources/read protocol handlers
- Self-contained widget HTML with MCP Apps bridge, drag-and-drop, client-side resize
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address review feedback — buffer slice, MIME type, HTML escaping
- Fix Buffer.buffer slab pool issue: slice to exact byte range to avoid
corrupted uploads for small files (≤4096 bytes)
- Update MIME type to image/jpeg after canvas re-encode (was keeping
original file.type, causing content-type mismatch in DB)
- Escape tx.date through esc() for consistent innerHTML sanitization
- Remove unused `reset` variable in tests
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>