* chore: remove Sentry, consolidate migrations, add test coverage
Remove @sentry/nextjs and all Sentry integration code — error tracking
now handled by Recapt. Consolidate 22 incremental migrations into a
single schema sync migration. Add 6 new test suites (auth, invoice
matching, VAT rules, opening balances) and extend report tests with
edge cases. Update Docker image name to gnubok, sync crontabs and
extension presets, fix CSP missing space, simplify journal entry
missing-document dialog.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: remove viewer bank import migration never applied to production
20260413150000_viewer_bank_import_permissions.sql (PR #234) was merged
to main but never applied to the production database. It references
current_active_company_id() which does not exist in production either.
This breaks fresh installs and Supabase preview branches because the
migration runs before the consolidated schema sync.
Remove it so the migration chain matches production. The viewer bank
import RLS policies should be re-added in a future migration alongside
the helper functions they depend on.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: correct delete policies for tables without company_id column
Seven tables in the generic delete-policy loop don't have a direct
company_id column, causing fresh installs to fail with "column
company_id does not exist". Fix by moving them out of the loop:
- invoice_items, journal_entry_lines, receipt_line_items,
supplier_invoice_items → join through parent table
- extension_toggles, notification_settings, push_subscriptions →
user-scoped (auth.uid() = user_id)
All policies match their existing production definitions.
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: complete multi-tenant refactor for reconciliation, arcim, settings validation
- Migrate bank-reconciliation to company_id (all functions + tests)
- Migrate arcim-migration entity mappers and orchestrator to company_id
- Fix enable-banking reconciliation calls to use companyId
- Add Swedish law validation to settings schema:
- VAT number required when VAT-registered (ML 11 kap. 8§)
- Moms period required when VAT-registered (SFL 26 kap.)
- Aktiebolag must use accrual accounting (BFNAR 2006:1)
- Fix fiscal year period creation: always 12 months after first year (BFL 3 kap.)
- Add plusgiro, website, pays_salaries fields to CompanySettings
- Add plusgiro to invoice PDF template
- Add fiscal period CRUD and opening balances API routes
- Add frame-src CSP directive for future iframe embedding
- Fix unlinked_1930_lines RPC to use company_id parameter
- Update CLAUDE.md documentation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address PR review findings (P1 + P2)
- Fix reconciliation events emitting companyId as userId — thread
actual userId through runReconciliation and manualLink
- Move VAT cross-field validation (vat_number, moms_period) from
schema refinements to route handler where effective stored state
is available, preventing false rejection on partial updates
- Add plusgiro format validation regex (N-N pattern)
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: 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>
* fix: trial balance silently truncated at 1000 entries, rename /nyckeltal to /kpi
Trial balance bug:
- The old implementation fetched journal entry IDs (capped at 1000 by
Supabase default limit), then queried lines via .in(entryIds) which
also hit URL length limits with large arrays of UUIDs.
- SIE imports create thousands of entries → KPIs showed zero.
- Replaced with a single joined query (journal_entry_lines → journal_entries)
using fetchAllRows() pagination. No row limit, no URL length issue.
- Removed the non-existent generate_trial_balance RPC call.
Page rename:
- /nyckeltal → /kpi (CLAUDE.md: all code in English)
- Nav label stays "Nyckeltal" (user-facing Swedish UI)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: select filtered columns in joined query, rename component, add redirect
- Select user_id/fiscal_period_id/status from journal_entries!inner()
so PostgREST applies embedded filters reliably (defense in depth)
- Rename NyckeltalPage → KpiPage per English code convention
- Add permanent /nyckeltal → /kpi redirect for existing bookmarks
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove ai-chat from extensions.config.json and docker/extensions.hosted.json
(kept in self-hosted config). Remove ChatWidget imports from dashboard layout
and root page. Reposition chat widget FAB and panel to bottom-right corner.
Regenerate extension registry.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add 'unsafe-inline' to script-src so Next.js hydration scripts run
- Whitelist *.enablebanking.com in CSP (script, style, connect, img)
- Allow HTTPS images broadly for third-party bank logos
- Clear stale refresh tokens in middleware (skip on /auth callback)
- Fix login button disabled on browser autofill by reading email from form DOM
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Vercel outage resolved — re-enable Sentry build-time integration for
source map uploads when SENTRY_AUTH_TOKEN is configured.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sentry runtime capture still works via instrumentation.ts. The build-time
wrapper can be re-added once SENTRY_ORG/PROJECT/AUTH_TOKEN are set on Vercel.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>