Commit Graph
16 Commits
Author SHA1 Message Date
Mattsson 8979f6eda3 Bug/year end failure (#575)
* feat: implement findNextPeriod function and integrate into year-end closing logic

* feat: add integrity check for PDF documents and enhance user feedback for corrupt files

* Refactor year-end service and period creation logic for improved UTC handling and error messaging

- Update `validateYearEndReadiness` to assert on stable warning messages without interpolating period names.
- Modify `createNextPeriod` to ensure date calculations are performed in UTC, preventing DST-related issues.
- Enhance error handling in `validateYearEndReadiness` and `executeYearEndClosing` to avoid exposing database details.
- Introduce structured error messages for year-end processes in `structured-errors.ts`.
- Add tests for document integrity checks, ensuring proper authentication and error handling.
- Implement GUC checks in document versioning to prevent unauthorized modifications and ensure company membership.
- Update migration scripts to reflect changes in document immutability enforcement.

* fix: add comment to clarify GUC behavior in document supersession logic
2026-05-27 14:19:30 +02:00
MattssonandClaude Opus 4.7 a2a556d837 Bug/UI wrong display (#573)
* fix(dashboard): exclude credit notes from unpaid invoices widget

Credit notes (status='sent', negative total) were summed into the
"Att få betalt" widget, producing confusing negative totals like
"2 st, -38 625 kr". Filter them out via credited_invoice_id IS NULL,
matching the existing pattern in reminder-processor and the AR ledger.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(documents): harden PDF preview and upload validation

- JournalEntryAttachments: switch inline PDF preview from <iframe> to
  <object type="application/pdf">. Mirrors the AttachmentPreviewSheet
  fix from #572 — Chrome's frame pipeline intermittently surfaced
  "Det här innehållet har blockerats" on iframes even with permissive
  CSP. <object> invokes the PDF plugin directly. crbug.com/271452.

- /api/documents/:id/inline: resolve Content-Type via file extension
  when mime_type is null or application/octet-stream. Legacy uploads
  landed with empty File.type from some drag sources; combined with
  the new X-Content-Type-Options: nosniff header on this route,
  Chrome refused to render valid PDFs. Extension fallback covers
  every legacy row without a DB backfill.

- /api/documents POST: surface DB-trigger period-lock errors as a
  400 DOC_UPLOAD_PERIOD_LOCKED with a Swedish reason. Previously
  every catch was bucketed into DOC_UPLOAD_STORAGE_FAILED (500 /
  "Filen kunde inte sparas") which hid the real cause from users
  attaching to verifikationer in closed/locked fiscal periods.

- document-service: add validateDocumentMagicBytes() that inspects
  the first bytes for valid PDF/PNG/JPEG/WebP headers (PDF tolerates
  a leading UTF-8 BOM). Wired into uploadDocument() and
  createNewVersion() so every upload path is protected — UI, MCP,
  and future email/webhook ingestion. Defends against agents that
  send a base64-encoded text placeholder instead of real binary
  bytes via the gnubok_upload_document MCP tool, which produced
  tiny (15-561 byte) "PDFs" that failed to render in Chrome and
  in external viewers.

Tests use a minimal valid PDF buffer (%PDF-1.4 … %%EOF).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(arsredovisning): emit ÅRL-required notes and FTE-weighted medelantal

Five compliance gaps fixed in the K2 and K3 noter builders:

- Anläggningstillgångar roll-forward per ÅRL 5:8 § — per-category IB
  anskaffningsvärde, tillkommande, avgående, UB and accumulated
  avskrivningar movement (was only emitting avskrivningstider).
- Långfristiga skulder förfallande efter mer än fem år per ÅRL 5:13 §.
- Ställda säkerheter and Eventualförpliktelser as separate notes per
  ÅRL 5:14-15 § (K2 previously combined them).
- Koncernförhållanden per BFNAR 2016:10 kap. 19 / BFNAR 2012:1 kap. 8.

Replaces medelantal anställda — the old query filtered employees by an
is_active column that doesn't exist, so the note never emitted. Now
uses an FTE-weighted day-based average per ÅRL 5:20 §.

Six disclosure fields persist on arsredovisning_narratives as per-period
overrides; the UI extends the existing förvaltningsberättelse editor
with a "Lagstadgade upplysningar" subsection sharing the same Spara
button — no new pages, no settings changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(invoices): respect vat_registered=false and hide personnummer for B2C

- PDF address block no longer prints org_number for individual customers
  (GDPR data minimization; ML 17 kap 24§ requires name + address only).
- Wire company_settings.vat_registered through the rule helpers, invoice
  creation API, preview-pdf API, and the new-invoice form so a non-VAT-
  registered seller cannot charge VAT (ML 1 kap. 1§). The PDF suppresses
  the empty "Moms 0%" row and shows a dedicated "Företaget är inte
  momsregistrerat" notice instead of the ML 3 kap. exempt notice.
- Engine unchanged: 'exempt' treatment already routes to 3004/3100 and
  skips VAT lines.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(settings): remove approval rules from sidebar and routes

* fix(invoices): ensure vat_registered defaults to true for invoice previews and API

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 11:01:53 +02:00
MattssonandClaude Opus 4.7 32d9978f1b Fix/chrome pdf preview csp (#572)
* feat: add option to exclude year-end closing entries in SIE export and related reports

* delete docs

* fix: allow Chrome's PDF viewer in verifikat document preview

The /api/documents/:id/inline route shipped with
`object-src 'none'` in its CSP, which blocked Chrome's built-in PDF
viewer (it renders inline PDFs via an internal <embed>). Users on
Chrome saw "Det här innehållet har blockerats" when expanding a PDF
attachment in the bookkeeping view; Firefox (PDF.js) and Edge (own
viewer) were unaffected, and JPGs worked because <img> isn't subject
to object-src.

Drops the CSP for this route to the minimum needed for embeddability:
`frame-ancestors 'self'`. X-Content-Type-Options: nosniff plus the
fixed Content-Type from the handler already block MIME confusion;
X-Frame-Options: SAMEORIGIN + frame-ancestors still block clickjacking.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(auth): add webmail deep link to email confirmation screens

Mirrors Stripe's signup UX: after asking the user to verify their email,
detect their webmail provider from the domain and show a button that
opens the inbox in a new tab. Gmail gets a from:<sender> search
pre-populated; Outlook/Yahoo/iCloud/Proton open the inbox directly.
Unknown / custom domains fall back to the existing copy.

Sender address is configurable via NEXT_PUBLIC_BRANDING_AUTH_EMAIL_FROM
(default noreply@gnubok.se) so white-label installs can match their
Supabase Auth SMTP config.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(auth): unblock first-time password set for BankID users with MFA

Supabase rejects updateUser({password}) and mfa.unenroll with "AAL2 session
is required" whenever a TOTP factor is enrolled. BankID magic-link logins
produce AAL1, and middleware skips MFA enforcement for bankid_linked users,
so they had no path to AAL2 — leaving them unable to set a backup password
or disable MFA without going through the email-recovery escape hatch.

- /api/account/password: branch on app_metadata.has_password. First-time set
  writes via service.auth.admin.updateUserById (no existing credential to
  protect, AAL2 guard does not apply). Change-password keeps the user-session
  updateUser so AAL2 still fires for credential rotation.
- /mfa/verify: accept a safeReturnTo query param and route there after
  successful verify, so step-up flows can land back where they came from.
- SecuritySettings: detect the AAL2 error from both change-password and
  mfa.unenroll and redirect through /mfa/verify?returnTo=/settings/account
  instead of toasting a dead-end error.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Add tests and rounding utility for öre precision in bokslut calculations

- Implemented `roundOre` function for rounding SEK amounts to two decimal places, ensuring consistent monetary calculations.
- Introduced `ORE_TOLERANCE` constant for comparing rounded amounts, facilitating invariant checks in financial entries.
- Created comprehensive tests for `roundOre`, covering typical cases, edge cases, and idempotency.
- Added year-end invariants tests to verify database-level guarantees for closing entries, ensuring they balance to the öre and reject discrepancies.
- Developed end-to-end tests for the dispositions chain, validating the correctness of calculations across various scenarios.

* fix: update PDF rendering to remove Swish QR code generation and set default to disable Swish visibility

* fix: enhance security by rejecting data URIs in safeReturnTo function tests

* fix: improve rounding logic in roundOre function and add customer_type migration

* fix: add customer_type column to customers and enforce CHECK constraint

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 22:29:41 +02:00
Mattsson 64bbeb4021 Fixed user issues (#559)
* Fixed user issues

* feat: add personal_number column to customers for individual identification

* feat: add personal_number field to makeCustomer function for enhanced customer identification

* feat: add personal_number column with constraint check for customer identification
2026-05-22 12:22:15 +02:00
MattssonandClaude Opus 4.7 5725c25bf1 Logs/improved logging (#398)
* feat(mcp): add create_transactions tool with /pending approval gate

New MCP tool gnubok_create_transactions stages 1–10 transactions per call
as pending_operations of type create_transaction (risk: medium). Each item
becomes its own card on /pending; on confirm, the executor inserts the row
into transactions with import_source='mcp' so MCP-staged ingestion is
distinguishable from PSD2 sync. Designed for skill workflows that pull
external data (e.g., Airtable) and want the user to gate the writes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(bas): strip concatenated group headers from corrupted account names

A chart-data import bug had glued the next group's header onto the last
account in each preceding group across all eight bas-data class files
(e.g. account 2670 read "Utgående moms på försäljning inom EU, OSS 27
PERSONALENS SKATTER, AVGIFTER OCH LÖNEAVDRAG"). The corrupted names
surface in transaction dropdowns, ledgers, SIE exports and årsredovisning,
and risk VAT miscategorization on the OSS (2670) and blandad-verksamhet
(6999) accounts specifically.

- Cleans 69 account_name and 64 description fields across class-1..8 files
- Adds a regression test asserting no name contains a concatenated header
- Ships an idempotent safety-net migration that updates already-seeded
  chart_of_accounts rows, gated on the corrupted string so user
  customizations are preserved

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(errors): add structured error codes and handling for various operations

- Introduced a new structured error registry in `structured-errors.ts` to standardize error handling across the application.
- Added Swedish and English messages for various error scenarios, including validation, authorization, and bookkeeping errors.
- Implemented a client-side error toast in `use-error-toast.ts` to display user-friendly error messages with remediation hints.
- Created a wrapper for recording operation outcomes in `record-operation.ts`, enhancing audit capabilities for operations.
- Developed a provider call wrapper in `with-provider-call.ts` to handle external HTTP calls with structured logging and error mapping.
- Added a new SQL migration to extend the processing history with new event types and aggregate types for better operational telemetry.

* Refactor supplier API routes to use context-based logging and error handling

- Replaced direct Supabase client usage in GET and POST routes with context-based approach using `withRouteContext`.
- Enhanced error handling to provide structured error responses for supplier creation and listing.
- Updated logging to include request IDs for better traceability.
- Introduced new error codes for supplier-related operations.
- Refactored tax deadlines cron job to utilize context and improved error handling.
- Updated ESLint configuration to enforce logging practices across API and lib directories.
- Enhanced arcim migration extension with structured error handling and logging.
- Added classification for provider errors to improve user-facing error messages.
- Introduced request ID in extension context for better log correlation.

* fix(route-context): update DynamicParams type for improved type safety in route handlers

* feat(transactions): add 'create_transaction' operation to PendingOperationType

* fix(route): ensure companyId is non-nullable in loadAndDeriveAbsence function

* fix(route-context): ensure companyId is always non-null by short-circuiting with COMPANY_CONTEXT_MISSING

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 11:12:02 +02:00
Mattsson fa7d4075cf Supp/invoice bfl errors (#390)
* feat(accounting): update accounting method validation and messaging for aktiebolag and enskild firma

* Remove AI subsystem and related code

- Deleted AI proposals and requests persistence logic from `lib/ai/proposals/persist.ts`.
- Removed re-validation logic for proposals in `lib/ai/proposals/re-validate.ts`.
- Cleaned up schemas related to AI flows in `lib/api/schemas.ts`.
- Removed AI-related fields from bookkeeping engine in `lib/bookkeeping/engine.ts`.
- Eliminated AI event types from `lib/events/types.ts`.
- Updated tests to reflect the removal of AI-related functionality in `lib/extensions/__tests__/sectors.test.ts`.
- Adjusted initialization logic in `lib/init.ts` to exclude AI proposal handler registration.
- Cleaned up transaction ingestion logic in `lib/transactions/ingest.ts` to remove AI flow checks.
- Updated helper functions in `tests/helpers.ts` to remove AI-related settings.
- Removed AI-related types and interfaces from `types/index.ts`.
- Added migration script to drop AI-related tables and settings from the database.

* fix(migrations): ensure foreign key constraint is dropped before removing AI tables

* feat(invoice-inbox): implement deterministic invoice field extraction and inbox provisioning

- Added `extract-invoice-fields.ts` for extracting fields from PDF invoices using regex and pdfjs-dist, replacing the previous AI classifier.
- Introduced `inbox-provisioning.ts` to manage company inbox addresses and rotation of inboxes using Supabase RPCs.
- Created `resend-inbound.ts` for handling inbound email events and attachments via the Resend API.
- Defined the extension manifest for the invoice inbox, specifying required environment variables and descriptions.
- Migrated database schema to remove AI-related columns and tighten the status enum in `invoice_inbox_items`.

* feat(invoice-inbox): remove AI-specific columns and tighten status enum

* fix(skattekonto): remove manual entry creation reference from transaction input

* fix(schemas): remove accounting method validation for aktiebolag in UpdateSettingsSchema
2026-05-05 09:53:37 +02:00
Mattsson a1a816b4a5 Delete features (#218)
* Implement company and account deletion features

- Add event types for company and account deletion to CoreEvent.
- Enhance Supabase middleware to handle company context resolution and cookie management for archived companies.
- Create API routes for deleting accounts and companies, including necessary validations and event emissions.
- Implement tests for account and company deletion endpoints to ensure proper functionality and error handling.
- Add retention notice component to inform users about bookkeeping data retention during destructive actions.
- Create database migrations to support soft deletion of companies and anonymization of user accounts, ensuring compliance with retention laws.

* feat: enhance account deletion process and update user notifications

* Add service client for onboarding completion check and update escape hatch visibility

* Enhance invite flow and email handling for company members

* Refactor company context and RLS policies for active company isolation

- Update `switchCompany` to remove unnecessary revalidation as client handles navigation.
- Revise `getActiveCompanyId` to prioritize `user_preferences` and validate against non-archived memberships.
- Modify `setActiveCompany` to ensure `user_preferences` is the authoritative source while maintaining cookie compatibility.
- Enhance middleware to resolve active company using `user_preferences` and fallback to first non-archived membership.
- Introduce new API route `/api/company/current` to fetch the active company ID for cross-tab synchronization.
- Implement `CompanyTabSync` component for real-time active company enforcement across tabs.
- Create migration for RLS policies to enforce single-active-company isolation using `current_active_company_id()`.

* feat: implement viewer role enforcement for write permissions

- Added `useCanWrite` hook to determine if the current user has write permissions based on their role in the active company.
- Updated various components (JournalEntryForm, CustomerForm, DeadlineForm, etc.) to disable write actions and show a lock icon with a tooltip for users without write permissions.
- Introduced `requireWritePermission` function to enforce write permissions at the API level, returning a 403 response for viewers.
- Created tests to verify the behavior of the viewer role and write permissions.
- Added database migration to enforce read-only access for viewers at the database level.
2026-04-11 17:06:32 +02:00
Jakob WennbergandClaude Opus 4.6 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>
2026-04-09 16:12:03 +02:00
Jakob WennbergandClaude Opus 4.6 1dcec370b6 fix: sanitize document filenames and add upload validation (#171)
* fix: sanitize document filenames and add server-side upload validation

Filenames with spaces or non-ASCII characters (e.g. Swedish ö, ä, å) caused
Supabase Storage to reject uploads with "Invalid key". This adds filename
sanitization, server-side size/type validation on both upload routes, and
fixes a duplicate-filename race condition in the upload UI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: require MIME type and handle empty sanitized filenames

Address review feedback:
- MIME type check now rejects files with missing/empty Content-Type
  instead of silently allowing them through
- Fallback to 'file' when sanitized base is empty (e.g. ööö.pdf)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 14:44:38 +02:00
MattssonandClaude Opus 4.6 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>
2026-03-31 16:41:52 +02:00
MattssonandClaude Opus 4.6 550cadcb06 fix: harden auth, cron secrets, and provider flows (GNU-17) (#148)
- Replace === with crypto.timingSafeEqual in all 7 cron routes via shared lib/auth/cron.ts
- Add in-memory rate limiting (60 req/min) and expires_at support to calendar feed
- Add exponential backoff on MFA verify after 3 failed attempts
- Add 60s cooldown on password reset requests
- Validate bank callback auth code format before API call
- Redact session IDs from bank sync and callback logs
- Validate OAuth redirect_uris against allowlist (claude.ai, claude.com, localhost)
- Remove excessive PII/debug console logging from login page

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 23:49:09 +02:00
Jakob WennbergandClaude Opus 4.6 4031ab680d fix: downgrade missing extension env vars to warning, add error boundaries and cron auth fixes
- Change missing extension env vars from throw to log.warn (graceful degradation)
- Move initialized flag after all init steps complete
- Add error.tsx and loading.tsx for dashboard error boundaries
- Fix cron route auth header checks
- Add ensureInitialized() to journal entry reverse and invoice mark-paid/sent routes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 15:09:23 +01:00
Jakob WennbergandClaude Opus 4.6 03b569d708 refactor: consolidate extension system to general-only with manifest-driven architecture
- Remove all sector-specific extensions (construction, ecommerce, export,
  hotel, restaurant, tech) — only general-purpose extensions remain
- Move NE-bilaga and SRU export from extensions to core reports (lib/reports/)
- Move moms-box-mapping from extensions/export/shared to lib/vat/
- Replace per-extension API routes with catch-all dispatcher
  (app/api/extensions/ext/[...path]/route.ts)
- Add manifest.json for each extension with metadata, env vars, and deps
- Add api-routes.ts pattern for extension-defined API endpoints
- Add code generation scripts (generate-extension-registry, create-extension)
- Add extensions.config.json for opt-in extension loading
- Add extensions.schema.json for config validation
- Add email service interface with noop default (lib/email/service.ts)
- Add CI workflow (core-build.yml) to verify core builds with zero extensions
- Add migration 045: expand account_type CHECK for untaxed_reserves
- Update CLAUDE.md with comprehensive extension system documentation
- Update all report engines and bookkeeping services for new imports
- Clean up extensions.schema.json to only list existing extensions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 14:32:56 +01:00
Jakob WennbergandClaude Opus 4.6 39e407644d feat: unified document inbox, full BAS 2026, and document-transaction matching
- Expand BAS reference from ~180 to ~1,276 accounts (full BAS Kontoplan 2026)
  with K2 exclusion flags, per-class data files, and computed SRU codes
- Evolve invoice inbox into unified document inbox handling invoices, receipts,
  and government letters with AI-powered classification (Claude Haiku Vision)
- Add multi-pass document-to-transaction matching engine with greedy assignment
  for both supplier invoices (reference/amount/date/name) and receipts
  (weighted amount/merchant/date scoring)
- Add supplier invoice matching in transaction ingest pipeline
- Inject booking template suggestions into AI extraction prompts
- Surface matched documents in swipe categorization UI with one-tap booking
- Auto-activate missing BAS accounts during SIE import against full reference
- Add K2 filter toggle in Chart of Accounts manager
- Add receipt confirmation route with BFNAR representation fields
- Add database migrations for K2 support and document matching columns
- Remove obsolete extension migration scripts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 16:59:02 +01:00
Jakob WennbergandClaude Opus 4.6 d0c0d8a7d2 feat: UX improvements — nav, reports tabs, dashboard alerts, transaction hints, settings layout
- Move Reports to Finans nav group and auto-expand Övrigt on its pages
- Make report tabs horizontally scrollable with gradient fade on mobile
- Surface deadlines and alerts above the fold on dashboard
- Add dismissible categorization hint card on transactions page
- Split settings company form into 4 separate Cards for scannability
- Add monthly breakdown report, document upload zone, journal entry attachments
- Add batch category selector, receipt document linking, invoice form improvements

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 17:16:22 +01:00
Jakob WennbergandClaude Opus 4.6 838dc6b8b5 refactor: clean up codebase, remove dead code and obsolete docs
Remove influencer-era documentation, unused components, boilerplate
assets, and ghost tiktok cron job. Add supplier invoice management,
document API routes, and PWA icons. Replace boilerplate README.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 12:23:17 +01:00