a652dcae1ae30209cd75dbdf1de98ec2d265ed88
9
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
a53a119a2e |
Fix/vat parent accounts (#438)
* feat(enable-banking): add support for account selection and syncing - Updated StoredAccount interface to include an 'enabled' flag for account syncing preferences. - Enhanced ensureFiscalPeriod function to handle overlapping fiscal periods with posted entries and opening balances. - Added tests for fiscal period validation and account syncing logic. - Implemented AccountPickerDialog component for user account selection. - Created API routes for PATCH /accounts and POST /sync to manage account syncing. - Introduced 'pending_selection' status for bank connections to allow user account selection before syncing. - Updated database migration to support new connection status and backfill existing accounts with enabled=true. * feat(enable-banking): implement account selection and consent event logging --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
81e9dd224e |
Add/csv import options (#420)
* feat(import): add customer and supplier parsing functionality - Implemented customer file parsing in `lib/import/customers/parser.ts` with support for Excel and CSV formats. - Created types for detected customer columns and parsed customer rows in `lib/import/customers/types.ts`. - Added tests for customer classification logic in `lib/import/shared/__tests__/classify.test.ts`. - Developed classification functions for customers and suppliers in `lib/import/shared/classify.ts`. - Introduced shared column utility functions in `lib/import/shared/column-utils.ts`. - Implemented supplier file parsing in `lib/import/suppliers/parser.ts` with validation for various fields. - Created types for detected supplier columns and parsed supplier rows in `lib/import/suppliers/types.ts`. - Added tests for supplier column detection and parsing in `lib/import/suppliers/__tests__/column-detector.test.ts` and `lib/import/suppliers/__tests__/parser.test.ts`. * fix(labels): update 'Svenskt företag' to 'Svenskt företag eller organisation' for clarity * feat(import): refactor encoding handling for Swedish files and add tests for character preservation * feat(recapt): implement clearRecaptIdentity function and integrate into logout flow * feat(bookkeeping): implement copy functionality and next voucher sequence retrieval * feat(import): enhance customer and supplier import functionality with normalization and event handling |
||
|
|
5c52f24a49 |
feat(mcp): agent-native improvements — progressive discovery, widgets, skills, telemetry (#393)
* feat(mcp): agent-native improvements — progressive discovery, widgets, skills, telemetry
Four coordinated streams of MCP server improvements that move gnubok toward
agent-first design, grounded in Anthropic's Nov 2025 "Code execution with MCP"
article and the May 2026 MCP conference talk.
Context budget — minimize tools/list payload
- New gnubok_search_tools: progressive discovery with name|summary|full detail
levels and scope filtering. Agents pull only the schemas they need.
- Trimmed all 50 tool descriptions from multi-paragraph blocks (avg ~500-1000
chars) to one-sentence summaries (avg ~120 chars). Args/Returns/Examples
blocks dropped — they duplicated inputSchema.
- outputSchema declared on every tool; structuredContent emitted on every
successful tools/call (was previously only widget-tagged tools).
- protocolVersion bumped to 2025-06-18 (negotiates back to 2024-11-05).
- Workflow examples consolidated into initialize.instructions.
- Net effect: tools/list payload ~43 KB / ~10.8K tokens for 51+ tools, with
headroom guard at 20K tokens.
MCP applications — server-shipped UI widgets
- New widgets/ directory with typed UiWidget contract; receipt-matcher moved
out of widget-html.ts (which was deleted) into widgets/receipt-matcher.ts.
- New gnubok_vat_review_widget tool + interactive momsdeklaration widget
(all 8 rutor with summary card, theme-aware light/dark, copy buttons).
- resources/list and resources/read iterate uiWidgets dynamically — adding
the next widget is a single file drop.
Skills over MCP — domain-knowledge primitive
- 5 user-facing SKILL.md-style workflow guides authored from existing
.claude/skills/swedish-* development skills:
• month-end-close — book → reconcile → VAT (monthly filers) → lock
• quarterly-vat-review — ruta-by-ruta map, deadlines, common errors
• year-end-close — bokslut, bokslutstransaktioner, lock → year-end
→ opening balances → close (irreversible)
• invoicing-rules — ML 17 kap. 24 §, customer types, ROT/RUT, Peppol
• payroll-monthly — salary run → calculate → review → AGI XML
- gnubok_list_skills (with optional tag filter) + gnubok_load_skill(slug).
Both unscoped — available to any authenticated key.
- Each skill also exposed as MCP resource at gnubok://skill/<slug>
(text/markdown) for forward compatibility with a future native
skills/list primitive.
Tool-call telemetry — measure before optimizing further
- Three new CoreEvent types (mcp.tool_called, mcp.tools_list_called,
mcp.resource_read), all persisted to event_log (30-day TTL, RLS-scoped).
- Fire-and-forget emission from the dispatcher — never blocks JSON-RPC
response, double-guarded against handler failures.
- tools/call instrumented at all four exit points (success, execution
error, scope denied, unknown tool). Latency measured tightly around
tool.execute() — excludes dispatcher overhead.
- tools/list logs returned tool count (informs progressive-discovery
adoption); resources/read logs URI + kind discriminator (widget /
skill / data / unknown).
- No PII or secret material in payloads — only metadata.
Out of scope (explicitly deferred):
- Code-mode SDK (no production code-mode hosts to consume it yet).
- Elicitations (require streamable HTTP transport — bigger architectural lift).
- DB lockdown / RPC funnel (foundational; should follow once telemetry tells
us where writes actually flow).
- CRUD → intent endpoints (frontend coupling — multi-PR effort).
Tests: +37 new unit tests across search-tools, output-schema, payload-size,
vat-review-widget, skills, telemetry. Existing receipt-matcher test updated
for the new structuredContent contract. 2,615 unit tests passing.
Production build green. No new lint warnings or errors in changed files.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(mcp): address PR #393 review findings
Greptile (P1 + P2) and the Swedish accounting compliance bot flagged 9 issues
across security, data correctness, and skill content. All addressed:
Security (P1)
- gnubok_search_tools: scope filter now fails closed when __keyScopes is
absent. The earlier permissive default leaked the full tool inventory if
the dispatcher's hard-coded name check ever silently broke. Marker presence
is part of the contract — explicitly empty array also hides scoped tools.
Two new test cases pin the fail-closed behaviour.
Compliance — VAT (data correctness)
- get_vat_report now aggregates 2614/2624/2634 (reverse-charge output VAT)
and exposes them as ruta30/ruta31/ruta32 per SKV 4700. ruta48 also picks
up 2647 (missing before). ruta49 formula corrected to
(10+11+12+30+31+32) − 48. The widget renders the new rutor between the
Utgående and Ingående sections.
- Widget ruta 05 sub-label updated from "3001+3002+3003" to "all momspliktig
försäljning oavsett skattesats" — ruta 05 covers all domestic taxable
supplies, not just direct-rate sales.
- Refactored: extracted computeVatReport() helper used by both
gnubok_get_vat_report and gnubok_vat_review_widget. Removes the
rename-fragile tools.find() lookup at runtime.
Compliance — payroll
- payroll-monthly skill: replaced "born 1958 or earlier = 10.21%" (the 2024
formulation) with the statutory rule "age 66+ on 1 January of the income
year (67+ from income year 2026)". Removed the unsourced "age 16–18:
11.78%" row in favour of a current växa-stöd description with explicit
Prop. 2025/26:34 reference and a "verify against current Skatteverket
tables" caveat.
Compliance — skills text
- invoicing-rules: added explicit footnote on the 1 April 2026 livsmedel
rate change. Restaurang/servering stays at 12 %; livsmedel sold in other
forms drops to 6 %. Per Prop. 2025/26:55.
- year-end-close: clarified periodiseringsfond cap as "25 % of överskott
before this year's avsättning" (IL 30 kap.), removing the ambiguous
"skattemässigt resultat" phrasing that could be misread as a circular
after-fond computation.
Schema correctness
- STAGED_OPERATION_SCHEMA.required gains "staged" — every path through
stagePendingOperation returns the field, so the schema now matches the
contract that MCP clients validate against.
Tests: 2,617 passing (+2 for the search-tools fail-closed cases).
Production build green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(mcp): address PR #393 round-2 compliance review
Round 2 of the swedish-compliance bot ran after the previous fix-push and
flagged four substantive items + a recommendation. All addressed:
VAT computation (data correctness)
- ruta05 expanded beyond 3001/3002/3003 to cover the common BAS taxable-
revenue accounts (3001-3008, 3041-3048, 3051-3058, 3071-3078). Companies
that book to 30xx alternates were previously under-reporting taxable
turnover; now all standard BAS taxable-revenue numbering contributes.
- One-sided reverse-charge warning: when output VAT is booked on
2614/2624/2634 (rutor 30/31/32 > 0) but the matching calculated input
VAT (2645) is zero, computeVatReport now returns a Swedish-language
warning string. ruta49 is inflated in this case — the warning surfaces
the most common reverse-charge error per the swedish-vat skill. The
widget renders warnings in a terracotta panel above the summary card.
- computeVatReport exported and a focused unit test added — exercises 2647
inclusion in ruta48, reverse-charge balanced/unbalanced cases, and the
expanded ruta05 mapping. Fills the gap that prior tools/call integration
tests couldn't reach.
Skill content
- payroll-monthly Step 6: BAS journal-entry example no longer hard-codes
31.42 % on the 7510/2730 lines. The avgift line is now described as
"avgift_base × applicable_rate per employee" with explicit aggregation
semantics for runs that mix full-rate and reduced-rate employees.
Aligns with the Step-4 reduced-rate caveats already in place.
- invoicing-rules ROT/RUT block: replaced the bare "30 % / max 50 000 SEK"
text with the full year-by-year picture — RUT 50 % / 75 000 max, ROT
baseline 30 % / 50 000 max, 2024 H2 doubled ceiling, 2025 May–Dec
enhanced 50 % rate. Defaults to "verify against current Skatteverket
table" rather than a single hard-coded rate.
False positives in the round-2 review (no fix needed; documented for the
record):
- "Old vat_report path still computes ruta48 without 2647" — the old path
was replaced by computeVatReport in the previous push; the bot was
reading the diff hunk and conflating it with current behaviour.
- "Widget prose says ruta49 = (10+11+12) - 48" — no such prose exists in
widgets/vat-review.ts. The skill body has the correct
(10+11+12+30+31+32)-48 formula.
- "Including 'reversed' status entries in VAT aggregation may over-count
cross-period storno" — current behaviour is correct per Skatteverket
period-aligned filing: the reversed original stays in its own period,
the matching storno (status 'posted') lands in the reversal period,
and they net to zero across the full year. Adding code comment to
document.
Tests: 2,623 passing (+6 for computeVatReport unit tests). Production
build green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(mcp): address PR #393 round-3 compliance review
Compliance bot re-ran after the round-2 push and flagged three items:
VAT computation
- One-sided reverse-charge warning previously only checked 2645 (EU
acquisitions). For domestic reverse charge per ML 16:13 (byggtjänster,
electronics > 100k SEK, etc.) the matching input lands on 2647 — a
correctly-balanced 2614+2647 booking would have falsely fired the
warning. Fixed: warning now triggers only when *both* 2645 and 2647
are zero. Updated message text mentions both accounts. Added a test
case asserting the no-warning path for 2647-only-input.
Skill documentation drift
- quarterly-vat-review skill body still showed ruta05 source as
"3001 + 3002 + 3003" while the runtime computeVatReport sums 32 BAS
taxable-revenue accounts. Updated the skill table to read
"3001–3008, 3041–3048, 3051–3058, 3071–3078" so the auditor-facing
docs match the implementation.
outputSchema upgrade
- gnubok_get_vat_report and gnubok_vat_review_widget previously declared
outputSchema as the bare { type: 'object' }. Replaced with a shared
VAT_REPORT_OUTPUT_SCHEMA constant declaring period, period_label, all
11 rutor (with descriptions referencing source accounts), summary,
and warnings. Modern MCP clients that validate structuredContent
against outputSchema now have an accurate contract. Added a test
asserting the schema is non-trivial and declares every ruta the
runtime returns.
Tests: 2,625 passing (+2 for the 2647 warning path and the
outputSchema shape assertion). Production build green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(mcp): address PR #393 round-4 compliance review
The compliance bot re-ran after the round-3 push with a fresh batch.
Real findings fixed; false positives documented.
VAT computation
- Removed 3004 (Försäljning inom Sverige, momsfri / VAT-exempt) from
RUTA_05_ACCOUNTS — round-2's expansion accidentally included it. Ruta 05
is the *taxable* base; exempt sales must NOT contribute. New test pins
the exclusion.
- Added 3106 (taxable EU goods supply, momspliktig) to RUTA_05_ACCOUNTS.
Used when EU buyer's VAT number is invalid or buyer is private.
- Added ruta35 — EU intra-community goods supplies, momsfri (account
3108). Previously omitted entirely from the rutor schema; SKV 4700
has it as a distinct box separate from ruta 39 (services) and ruta 40
(export outside EU). VatReportResult, VAT_REPORT_OUTPUT_SCHEMA, the
widget table, the copy-summary block, and the quarterly-vat-review
skill table all updated. New test covers 3108 → ruta35 mapping.
- Strengthened the comment on the posted+reversed status filter to
document why current behavior is correct per ML 2023:200 and
faktureringsmetoden (the bot's cross-period storno concern is a false
positive — see commit message rationale below).
Skill content
- invoicing-rules: added explicit BFL 5 kap. 6–7 § / ML 17 kap. 22–23 §
note that the kreditfaktura itself consumes a sequential number from
the same (or dedicated KR-) fakturaserie. The KR- prefix is a display
convention; the underlying löpnummer must be unbroken just like the
regular series.
- payroll-monthly: added the missing "born 1937 or earlier → 0 %"
cohort to the rate breakdown. Previously could lead a payroll run to
over-pay avgifter on the oldest cohort.
False positives in the round-4 review (verified, not changed)
- 2644/2648 as reverse-charge inputs: verified against gnubok's actual
BAS chart (lib/bookkeeping/bas-data/class-2-equity-liabilities.ts).
2644 does not exist; 2648 is "Vilande ingående moms" (dormant input
VAT for cash method), not RC at 6 %. Canonical RC inputs are 2645 (EU)
and 2647 (domestic) — both already covered.
- Cross-period storno over-count: per ML 2023:200 + Skatteverket
faktureringsmetoden, the original sale's VAT belongs to the invoice-
date period; the kreditfaktura's reduction belongs to the storno-date
period. Including 'reversed' status entries (which still have their
original date) is therefore correct. *Excluding* them would
under-report the original period and over-credit the reversal period.
Added a multi-line comment in computeVatReport documenting this.
Tests: 2,627 passing (+2 for ruta35 mapping and 3004 exclusion).
Production build green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
a0485ca1c1 |
fix: BankID signup takeover + supplier invoice dedup + event_log RLS visibility (#358)
* fix(tic): reject BankID signup when email is already registered (CWE-287) Signup previously linked BankID to any pre-existing profile matching the submitted email. Because BankID proves identity but not email ownership, an attacker who knew a victim's email could bind their own BankID to the victim's account and then log in via BankID (which skips TOTP MFA). Now signup returns 409 account_exists; the register page shows a Swedish error toast and redirects to /login so the user can authenticate with their password first and link BankID from settings (via the authenticated /bankid/link route that already exists). Covered by new bankid-complete.test.ts with an explicit regression test asserting no side-effects occur on the account_exists path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(bookkeeping): prevent duplicate registration entries for supplier invoices The invoice-inbox convert flow creates the registration journal entry inline and then emits supplier_invoice.confirmed. The core handler was also creating one, producing a second voucher on 2440/2641/expense and overwriting registration_journal_entry_id on the row. Two guards in the core handler: - Payload guard: skip if supplierInvoice.registration_journal_entry_id is already set (fast path for callers that include it in the payload). - DB re-fetch guard: re-read the row and skip if it has been linked since the payload was built (handles stale-payload callers). The inbox extension now stamps registration_journal_entry_id onto the in-memory invoice before emitting so the fast path trips. Also fixes a latent bug where the handler filtered company_settings by userId instead of companyId, which would have selected the wrong row (or none) on multi-company accounts. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(events): write company_id on event_log rows and refuse unscoped events event_log has a company-scoped SELECT RLS policy, so rows written with NULL company_id are invisible to every user — effectively silently dropped from the automation feed. The handler now reads companyId from the payload (all persisted event types mandate it in TS) and includes it in both single and batch inserts. If a caller ever bypasses the type system and emits without companyId, the handler logs an error and skips persistence rather than writing a poisoned row. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: address PR review nits (event-log meta strip, redirect timer) - event-log-handler: rename stripUserId → stripMetaFields and also drop companyId from the stored data JSONB so it isn't duplicated alongside its dedicated column. - register page: drop the 1500ms setTimeout before router.push('/login') on the account_exists branch — the timer had no cleanup and fired a stale-closure push if the component unmounted first. The toast survives the route change via the root layout's Toaster. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
e46654ab25 |
feat: concurrency guards, account validation, and reversal side-effects (#247)
* feat: add concurrency guards, account validation, and reversal side-effects to bookkeeping engine Prevent double-booking via CAS guards on mark-paid and categorize routes (409 on conflict), make payment GL entries blocking (AP/AR must match GL), validate account resolution in engine, and auto-sync invoice status on payment reversal. Adds journal_entry.reversed event type. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address Greptile review — company_id filter, voucher gaps, status restore - Add missing company_id filter on supplier-invoice CAS update (defense in depth) - Add voucher_gap_explanations insert on CAS-cancelled entries in both mark-paid routes (BFNAR 2013:2 compliance, matching categorize route pattern) - Fix reversal status restore: check due_date to determine overdue vs sent/approved instead of always reverting to sent/approved - Rename shadowed reversedLines variable to originalLines (P2 clarity) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: derive reversal payment amount from payments table, not GL lines The reversal GL entry is already a line-by-line mirror per BFL 5 kap 5§. For the business-level invoice sync, use the payment record amount from supplier_invoice_payments / invoice_payments instead of inspecting GL account numbers — works identically for kontantmetod and faktureringsmetod without needing to know which accounts were used. Also adds company_id filter on all reversal sync queries (defense in depth). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: allow reversal of partially_paid customer invoices Widen the status filter from .eq('status', 'paid') to .in('status', ['paid', 'partially_paid']) so that reversing a partial payment GL entry correctly updates the invoice state. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
b484e9a7b4 |
fix: Swedish VAT/SIE compliance, storno hardening, document integrity (#209)
* feat: add INK2 declaration improvements, invoice delivery date, and Swedish compliance skills Expand INK2 engine with full INK2S/INK2R support and improved SRU generation. Add delivery_date field to invoices and corresponding PDF/migration support. Add Claude skills for Swedish asset accounting, invoice compliance, SIE import/export, SRU filing, and tax planning. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address PR review — map BAS 4500–4899, strip CRLF in SRU, document P3 - Map BAS accounts 4500–4599 (legoarbeten), 4700–4899 (diverse varuinköpskostnader) to SRU 7512 so they are not silently dropped from INK2R declarations - Strip \r\n in sanitizeString to prevent CRLF injection in SRU fields - Document P3 period suffix limitation for brutet räkenskapsår Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: correct BAS 4500-4599, 4700-4899 mapping from 7512 to 7511 Per the official BAS-to-SRU mapping, these account ranges are cost of goods (legoarbeten, inkurans, svinn) and belong under 7511 (Råvaror och förnödenheter), not 7512 (Handelsvaror). 7512 remains 4600-4699. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: Swedish VAT compliance — representation VAT, domestic RC, full BAS 26xx mapping, SIE encoding - Representation expenses now default to reduced_12 VAT (ML 13 kap 24-25 §§); income tax deduction was abolished 2017 but VAT deduction at 12% remains - Domestic reverse charge (byggtjänster etc.) uses 2647 instead of 2645, with distinct line descriptions for Swedish vs EU/non-EU RC - VAT declaration maps all BAS 26xx variant accounts (egna uttag 2612/2622/2632, uthyrning 2613/2623/2633, VMB 2616/2626/2636, import 2615/2625/2635, domestic RC 2647, frivillig skattskyldighet 2642) and revenue variants (3108/3105/3004/3100) to correct momsdeklaration rutor - SIE parser: remove unreliable #FORMAT PC8 encoding detection (most software exports UTF-8 with PC8 header), parse #FLAGGA for import-already-done warning, default SIE type to 1 when absent, fix RTRANS/BTRANS documentation - SIE export: add #RAR -1 (previous fiscal year), fix UB = IB + movements - Error messages: add pattern matching for locked period trigger errors Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address Greptile review — update ruta49 JSDoc, use null sentinel in error map Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: harden storno CAS guard, document integrity, and BFNAR archive compliance - Storno: defer original→reversed until both entries succeed, add CAS guard for concurrent reversals, use cancelEntry() instead of delete - Document: add document.accessed event, enrich archive manifest with metadata, add BFNAR 2013:2 systemdokumentation to full archive export - Verify cron: run daily, configurable batch size, include company_id in audit - Migrations: integrity audit actions, document version chain, metadata immutability, audit deletions, fix immutability for posted/cancelled Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address Greptile review — allow is_current_version in immutability trigger, log cancelEntry errors - Remove is_current_version from blocked fields in enforce_document_metadata_immutability trigger so create_document_version RPC can supersede documents linked to posted entries - Add error logging to cancelEntry for observability on cleanup failures Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
0dd1f5ebc1 |
feat: multi-tenant company refactor (GNU-19) (#153)
* feat: multi-tenant company refactor (GNU-19) Introduce companies table, company_members, and user_preferences to support multiple companies per user. All data scoping changes from user_id to company_id across the entire codebase. Key changes: - Database migration: new tables, company_id on 40+ tables, backfill, RLS rewrite from user_id to company-member-based, updated RPCs - Types: Company, CompanyMember, CompanyRole, UserPreferences types; company_id added to all entity interfaces; companyId on all events - Engine: all 7 core functions take companyId; storno, period, year-end services updated; 16 report generators updated - Middleware: company context resolution (cookie → prefs → first company) - API routes: ~120 routes updated with requireCompanyId() - Frontend: CompanyProvider context, layout/dashboard/onboarding updated - Extensions: context factory, 9 extensions, all lib files updated - Tests: 1880 tests passing, all helpers updated with company_id defaults Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: add database migrations for multi-tenant company and team system (GNU-19) Adds company_invitations, company creation RPC, team_members, account deletion RPC, and teams table refactor migrations. Updates base multi-tenant migration with cascading FKs and onboarding_step column. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: add team types and update core infrastructure for multi-tenancy (GNU-19) Adds TeamRole, MemberSource, and Team types. Refactors Supabase service client to be stateless, updates middleware for team-aware routing, extends CompanyContext with team/role fields, and updates extension service types to accept companyId. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: thread company_id through business logic functions (GNU-19) Replaces user_id scoping with company_id across all lib modules: bookkeeping, documents, transactions, invoices, reconciliation, tax, deadlines, and import. Updates corresponding tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: thread company_id through API routes and extensions (GNU-19) Updates all existing API routes to extract and pass companyId. Updates enable-banking and arcim-migration extensions for company-scoped transaction ingestion and sync. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: add company and team management API routes (GNU-19) Adds CRUD endpoints for company members, company invitations, team members, and team invitations. Includes invite token utilities, email templates, and company switch server action. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: add team/company UI components, pages, and dashboard updates (GNU-19) Adds CompanySwitcher, ConsultantEmptyState, Step0RoleChoice, company members and team management panels. Updates dashboard layout for team-aware routing, onboarding for multi-step role choice, and auth callback for team invite acceptance. Ignores supabase/.branches/. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: add null guards for company in import page (GNU-19) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: move appUrl declaration to outer scope in invite route (GNU-19) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: add optional chaining for company.name in members section (GNU-19) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: add optional chaining for second company.name in members section (GNU-19) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: add null guards for company in extension components (GNU-19) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: pass companyId to executeSIEImport in arcim-migration extension (GNU-19) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: update tests to use companyId instead of userId and improve type handling --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
5cb8c3c1e4 |
feat: support contact links and SIE import UX polish (#138)
* 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> * feat: add support contact links and improve SIE import UX Add a SupportLink component with a contact dialog throughout the app (nav, help page, settings, MFA, error pages, empty states). Improve SIE import flow with phased loading states, structured skip breakdowns, and an elapsed-time counter. Fix MFA enroll stale factor cleanup and URL encoding for settings return path. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address PR review — open redirect, XSS, test cleanup, fallback email - Validate returnTo is a relative path in MFA enroll (prevents open redirect) - Add afterEach import to event-log-handler tests (fixes handler leak) - HTML-escape user-supplied subject and message in support email body - Replace hardcoded personal email with support@gnubok.se fallback Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
f3ae3cd361 |
feat: event log, pending operations, and MCP staging (#135)
* 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> |