From cd64c0e3fbb90d9245050767dc9bde6d49ff0f5b Mon Sep 17 00:00:00 2001
From: Jakob Wennberg <149234542+jakobwennberg@users.noreply.github.com>
Date: Tue, 28 Apr 2026 18:26:03 +0200
Subject: [PATCH] feat(skatteverket): production-ready momsdeklaration
submission (#380)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* feat(skatteverket): production-ready momsdeklaration submission
Brings the Skatteverket extension up to a state where it can ship moms
declaration submission to Vercel production. Verified end-to-end against
SKV's Komplett testtjänst — all 8 momsdeklaration operations tested
(kontrollera, spara/hämta/radera utkast, lås/lås upp, hämta inlämnade,
hämta beslutade) plus signing-link return.
Bundles three coherent changes:
1. Skatteverket extension (the main work)
- extensions.config.json: enable `skatteverket`, drop `invoice-inbox`
and `ai-agent` (those were enabled in config but lacked AWS env vars
in prod, so they loaded but failed at runtime)
- lib/reports/vat-declaration.ts: extend ACCOUNT_RUTA to populate
Ruta 06 (uttag 3401–3403), Ruta 20–24 (reverse-charge bases from
4xxx cost accounts), Ruta 50 (import 4545–4547), and Ruta 42
(3404/3994/3980); delete the supplier-type heuristic that made
Ruta 20 and Ruta 23 always 0
- extensions/general/skatteverket/lib/token-store.ts: work around
three real prod schema-drift issues — wrong column on read/delete
(was `company_id`, schema only has `user_id`), missing
UNIQUE(user_id) constraint that makes UPSERT fail (switched to
DELETE+INSERT), missing RLS policies (switched to service-role
client). Refresh path now reuses existing row's company_id when
none is passed.
- extensions/general/skatteverket/index.ts: 9 sites switched from
ctx.companyId to ctx.userId for the token-store key; pass
companyId from the OAuth callback
- extensions/general/skatteverket/types.ts + components/reports/
SkatteverketPanel.tsx: align field names with v1.0.24 RAML
(signeringsLank/kontrollResultat/resultat/kod/status/beskrivning).
Without this, the signing link never displayed.
- SkatteverketPanel: add Lås upp + Radera utkast + Hämta utkast +
Hämta beslut buttons so the full lifecycle is reachable from the UI
- lib/reports/__tests__/vat-declaration.test.ts: rewritten to match
the refactored calculator; new fixtures for cost-account-based
reverse charge (Ruta 20/21/22/23/24), Ruta 50 import, Ruta 06
uttag, Ruta 42 expansion; SKV §4.1.1.4 cross-field contract checks
- supabase/migrations/20260428120000_skatteverket_tokens_user_id_unique.sql:
idempotently adds the missing UNIQUE(user_id) constraint
- scripts/*: dev-only helpers used during the prod-of-test
verification (create test company, seed VAT data, inspect token
state, etc.)
2. Journal-entries cancelled-status filter
- app/api/bookkeeping/journal-entries/route.ts: when no status filter
is supplied, exclude `cancelled` entries by default
- supabase/migrations/20260428153500_journal_entries_with_related_exclude_statuses.sql
3. Swedish e-invoicing skill (reference docs only — no runtime code)
- .claude/skills/swedish-e-invoicing/
Co-Authored-By: Claude Opus 4.7 (1M context)
* fix(skatteverket): address PR review findings
- panel: handleFetchDraft read `result.data?.last` (typo) — switched to
`result.data?.locked` to match the field defined in
SkatteverketUtkastResponse and the v1.0.24 RAML. The "(låst)" suffix on
the success message would silently never appear before this fix.
- api-client: getValidToken had no concurrency guard, so two parallel
SKV requests from the same user could both call /token with the same
refresh_token. SKV rotates the refresh_token on first use, so the
second call would 401 with REFRESH_EXHAUSTED-adjacent failures. With
the new 6-button UI on SkatteverketPanel, rapid clicks made this a
realistic trigger. Added an in-process Promise map keyed on userId
that coalesces concurrent refresh attempts; cross-process races are
mitigated by re-reading tokens inside the critical section before
calling refreshAccessToken (if another process refreshed already, we
use the newer token instead of burning the old refresh_token).
- migration 20260428120000: dedup query used `created_at < max(...)`,
which failed to remove duplicates inserted in the same second. The
subsequent ALTER TABLE … ADD CONSTRAINT would then abort. Switched
to ctid (Postgres physical row identifier) to break timestamp ties.
Co-Authored-By: Claude Opus 4.7 (1M context)
* fix(skatteverket): throw on token-store SELECT error before destructive DELETE
The company_id pre-read in storeTokens used destructuring that discarded
the error field. If the service-role SELECT failed for any reason (network
blip, overloaded DB, transient permissions issue), `existing` became null,
`resolvedCompanyId` stayed undefined, and execution fell through to the
DELETE. The old row got deleted successfully, then the INSERT omitted
company_id and failed with the NOT NULL constraint violation — leaving
the user with no token row at all and forcing a fresh BankID handshake.
Now we capture the SELECT error and throw before the DELETE runs.
Co-Authored-By: Claude Opus 4.7 (1M context)
---------
Co-authored-by: Claude Opus 4.7 (1M context)
---
.claude/skills/swedish-e-invoicing/SKILL.md | 56 ++
.../references/consumer-and-b2c.md | 115 ++++
.../references/european-mandates.md | 129 +++++
.../references/implementation-guide.md | 205 +++++++
.../references/legal-and-regulatory.md | 161 ++++++
.../references/market-provider-pricing.md | 132 +++++
.../references/peppol-bis-billing.md | 241 ++++++++
.../references/peppol-network.md | 172 ++++++
.../references/swedish-cius-and-specifics.md | 315 +++++++++++
.../journal-entries/__tests__/route.test.ts | 17 +
app/api/bookkeeping/journal-entries/route.ts | 2 +
components/reports/SkatteverketPanel.tsx | 239 ++++++--
extensions.config.json | 2 +-
extensions/general/skatteverket/index.ts | 24 +-
.../general/skatteverket/lib/api-client.ts | 40 +-
.../general/skatteverket/lib/token-store.ts | 101 +++-
extensions/general/skatteverket/types.ts | 24 +-
.../_generated/enabled-extensions.ts | 3 +-
lib/extensions/_generated/extension-list.ts | 6 +-
.../_generated/sector-definitions.ts | 33 +-
lib/extensions/_generated/workspace-map.tsx | 1 -
lib/reports/__tests__/vat-declaration.test.ts | 532 ++++++++++--------
lib/reports/vat-declaration.ts | 164 ++----
scripts/clean-skv-test-drafts.ts | 76 +++
scripts/create-skv-test-company.ts | 143 +++++
scripts/inspect-skv-readiness.ts | 166 ++++++
scripts/inspect-skv-tokens-table.ts | 51 ++
scripts/list-dev-users.ts | 45 ++
scripts/seed-skv-test-data.ts | 317 +++++++++++
scripts/set-arcim-org-number.ts | 93 +++
scripts/set-company-settings-org.ts | 102 ++++
scripts/setup-skv-test-company.sql | 41 ++
scripts/test-skv-other-endpoints.ts | 138 +++++
...000_skatteverket_tokens_user_id_unique.sql | 39 ++
..._entries_with_related_exclude_statuses.sql | 110 ++++
35 files changed, 3549 insertions(+), 486 deletions(-)
create mode 100644 .claude/skills/swedish-e-invoicing/SKILL.md
create mode 100644 .claude/skills/swedish-e-invoicing/references/consumer-and-b2c.md
create mode 100644 .claude/skills/swedish-e-invoicing/references/european-mandates.md
create mode 100644 .claude/skills/swedish-e-invoicing/references/implementation-guide.md
create mode 100644 .claude/skills/swedish-e-invoicing/references/legal-and-regulatory.md
create mode 100644 .claude/skills/swedish-e-invoicing/references/market-provider-pricing.md
create mode 100644 .claude/skills/swedish-e-invoicing/references/peppol-bis-billing.md
create mode 100644 .claude/skills/swedish-e-invoicing/references/peppol-network.md
create mode 100644 .claude/skills/swedish-e-invoicing/references/swedish-cius-and-specifics.md
create mode 100644 scripts/clean-skv-test-drafts.ts
create mode 100644 scripts/create-skv-test-company.ts
create mode 100644 scripts/inspect-skv-readiness.ts
create mode 100644 scripts/inspect-skv-tokens-table.ts
create mode 100644 scripts/list-dev-users.ts
create mode 100644 scripts/seed-skv-test-data.ts
create mode 100644 scripts/set-arcim-org-number.ts
create mode 100644 scripts/set-company-settings-org.ts
create mode 100644 scripts/setup-skv-test-company.sql
create mode 100644 scripts/test-skv-other-endpoints.ts
create mode 100644 supabase/migrations/20260428120000_skatteverket_tokens_user_id_unique.sql
create mode 100644 supabase/migrations/20260428153500_journal_entries_with_related_exclude_statuses.sql
diff --git a/.claude/skills/swedish-e-invoicing/SKILL.md b/.claude/skills/swedish-e-invoicing/SKILL.md
new file mode 100644
index 00000000..591de1c1
--- /dev/null
+++ b/.claude/skills/swedish-e-invoicing/SKILL.md
@@ -0,0 +1,56 @@
+---
+name: swedish-e-invoicing
+description: >
+ Swedish e-invoicing (e-fakturering) reference. Covers Lag 2018:1277 B2G mandate, Peppol BIS Billing 3.0, EN 16931, UBL 2.1, AS4, SMP/SML, DIGG, Sweden CIUS rules (SE-R-005 F-skatt, SE-R-011 Bankgiro/Plusgiro), VAT codes, ViDA mandate (1 July 2030), Dir. 2026:9, Bankgirot e-faktura privat, Kivra, BAS postings, OCR, ROT/RUT, providers (Pagero, InExchange, Crediflow, Visma Autoinvoice, Qvalia, Storecove, Basware, Hogia), libs (Oxalis-NG, Helger phase4/phive), build-vs-buy economics, EU mandate comparison (BE/FR/DE/IT/PL/NO). Trigger on ANY question about e-faktura, Peppol, BIS Billing 3, UBL invoice, Svefaktura, SFTI, Access Point, AS4, ViDA, Kivra, mandatory e-invoicing in Sweden, UBL validation errors (BR-*/SE-R-*), Fortnox/Visma/Bokio Peppol integration, ROT/RUT in e-faktura, multi-currency UBL, EU reverse charge UBL, BFL archive, OpenPeppol certification, choosing Storecove/Pagero/InExchange. Always use over training data, specs change biannually.
+---
+
+# Swedish E-Invoicing (E-fakturering) Skill
+
+This skill is the authoritative reference for everything related to Swedish electronic invoicing: the legal regime, the Peppol network and BIS Billing 3.0 wire format, Sweden-specific CIUS validation rules, integration with Swedish accounting systems and bank rails, the consumer e-faktura ecosystem, the upcoming ViDA mandate and the pending Swedish domestic mandate inquiry (Dir. 2026:9), and concrete implementation strategy for software builders.
+
+The data in Claude's training is **stale and unreliable** for this domain. Peppol specifications update twice yearly (May / November releases). The Peppol PKI migrated G2→G3 in late 2025. ViDA was adopted 11 March 2025 and entered into force 14 April 2025. Swedish Dir. 2026:9 was issued 5 February 2026. Skatteverket gained expanded online-audit rights from 1 April 2026. **Always consult this skill rather than answering from priors.**
+
+## Routing: which reference to load
+
+Use the table below to decide which reference file(s) to read. Multiple files often apply to a single question; load all relevant ones.
+
+| Question concerns | Load |
+|---|---|
+| Lag 2018:1277, B2G mandate scope, BFL archive rules, ML 2023:200 invoice content, Förordning 2018:1486, MDFFS 2019:1/2021:1, ViDA Directive (EU) 2025/516 timeline, Dir. 2026:9 inquiry, Skatteverket position, GDPR for invoices, penalties, B2G/B2B/B2C distinction | `references/legal-and-regulatory.md` |
+| UBL 2.1 invoice structure, EN 16931 BT-* business terms, mandatory header (CustomizationID, ProfileID, InvoiceTypeCode), UNCL5305 VAT category codes (S/Z/E/AE/K/G/O), calculation rules (BR-CO-13/15/17, BR-S-08 etc.), document type identifiers, BIS suite (Billing, Self-Billing, Catalogue, Despatch Advice, Invoice Response, MLR, MLS), Peppol BIS 4.0 / PINT convergence | `references/peppol-bis-billing.md` |
+| Peppol 4-corner architecture, AS4 v2.0 transport, SMP/SML lookup with NAPTR/SHA-256 algorithm, SBDH v1.2 with C1 country code, PKI G3 certificates, becoming a certified Access Point or Service Provider, OpenPeppol membership tiers and pricing, Peppol Testbed conformance | `references/peppol-network.md` |
+| Sweden-specific CIUS rules (SE-R-005 "Godkänd för F-skatt", SE-R-006 VAT rate restriction, SE-R-008/009 Bankgiro, SE-R-010 Plusgiro, SE-R-011 PaymentMeansCode 30, SE-R-013 Luhn orgnr), Swedish VAT (25/12/6/0%) encoding, OCR reference (BT-83), Bankgiro/Plusgiro PaymentMeans encoding, ROT/RUT and grön teknik handling, BAS-kontoplan postings for AR/AP, faktureringsmetoden vs kontantmetoden, multi-currency with TaxCurrencyCode, BT-10 BuyerReference per-buyer formats, Peppol identifier schemes (0007/0088/0192/0184/0037/0208/0204), F-skatt registration | `references/swedish-cius-and-specifics.md` |
+| Choosing between Pagero/InExchange/Crediflow/Visma Autoinvoice/Maventa/Qvalia/Tietoevry/Basware/OpusCapita/Hogia/Ropo Capital/Storecove, market shares, pricing benchmarks (per-document, monthly minimums), DIGG Peppol traffic statistics, how Fortnox/Bokio/SpeedLedger/Björn Lundén white-label their Peppol layer, API capabilities of major providers | `references/market-providers-pricing.md` |
+| Consumer e-faktura: Bankgirot e-faktura privat, EFA / e-giro format, Anslutningsärende/Anmälningsärende, bank participants, Kivra digital mailbox (volumes, pricing, ownership, Tink/Swish integration), Min Myndighetspost, distinction between consumer rails and Peppol | `references/consumer-and-b2c.md` |
+| Comparing Sweden to Belgium (2026 decentralised Peppol mandate), France (PA/PPF 2026-2027), Germany (XRechnung phased 2025-2028), Italy (SDI clearance), Poland (KSeF Feb/Apr 2026), Romania (e-Factura), Norway (proposed 2028), Spain, ViDA cross-border 1 July 2030 mandate, ViDA 2035 alignment deadline for legacy CTC regimes, predicting Sweden's likely model | `references/european-mandates.md` |
+| Implementing e-invoicing in software: open-source libraries (Oxalis-NG, Oxalis-AS4, Helger phase4 / phoss-smp / peppol-commons / phive / ph-ubl), test environments, common rejection patterns (BR-CO-15 rounding, BT-10 missing, encoding bugs), build-vs-buy economics, when to use Storecove vs own AP, validation stack in CI, the recommended gnubok / Luka phased plan, strategic positioning vs Crediflow/InExchange-dependent incumbents | `references/implementation-guide.md` |
+
+## Core facts that govern every answer
+
+These are short enough to inline; the references expand each.
+
+**Legal status (April 2026):** B2G mandatory since **1 April 2019** (Lag 2018:1277). B2B **voluntary**. B2C uses bank rails / Kivra, not Peppol. ViDA cross-border B2B mandate hard date: **1 July 2030**. Domestic mandate inquiry: **Dir. 2026:9 issued 5 Feb 2026, final report 30 Nov 2027**. Realistic Swedish domestic mandate window: **2029–2031** on a Belgium-style decentralised Peppol model.
+
+**Wire format:** Peppol BIS Billing 3.0, UBL 2.1 syntax, EN 16931 semantic. CustomizationID = `urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0`. ProfileID = `urn:fdc:peppol.eu:2017:poacc:billing:01:1.0`. Current release: **Billing 3.0.20 (November 2025)**. BIS 4.0 / PINT convergence in late 2025 / early 2026.
+
+**Network:** Peppol four-corner (C1 sender → C2 sending AP → C3 receiving AP → C4 receiver). AS4 v2.0 over HTTPS. SMP discovery via NAPTR/SHA-256 (migrated from CNAME/MD5 in 2025). PKI: G3 only after end-2025. SMP servers must run on port 443 from **1 February 2026**.
+
+**Authority:** DIGG is Sweden's Peppol Authority, regulator under Lag 2018:1277. **DIGG's Peppol-ID: `0007:2021006883`. Skatteverket: `0007:2021005448`.** Per regeringsbeslut Fi2025/01826, Peppol functions transfer to **Upphandlingsmyndigheten on 1 July 2026**; DIGG merges into PTS by 1 January 2027. SFTI ESAP 6 (EDIFACT) was removed 1 July 2025; Svefaktura is deprecated.
+
+**Identifier formats:** Swedish orgnr → `schemeID="0007"`, 10 digits no dash. Swedish VAT ID → `SE` + 10 digits + `01` (e.g. `SE556732100001`), prefix mandatory (BR-CO-9). For sole proprietors **DIGG recommends GLN (`0088`) over personnummer (`0007`) for GDPR**.
+
+**Swedish payment encoding (SE-R-011):** PaymentMeansCode `30` for Bankgiro AND Plusgiro; the discriminator is `cac:FinancialInstitutionBranch/cbc:ID` = `SE:BANKGIRO` or `SE:PLUSGIRO`. Legacy codes 56 / 50 are forbidden. Bankgiro 7–8 digits (SE-R-008/009), Plusgiro 2–8 chars (SE-R-010). OCR reference goes in `cbc:PaymentID` (BT-83), Luhn-validated.
+
+**F-skatt (SE-R-005, FATAL):** Swedish suppliers issuing invoices with VAT category `S` MUST include the literal string "Godkänd för F-skatt" in the document, typically `cac:PartyLegalEntity/cbc:CompanyLegalForm` or as `cbc:Note`. Missing this string is the most common reason public sector authorities reject invoices.
+
+**Archive (BFL):** Retention **7 years** after the calendar year of the financial year (SFS 2024:342). The inbound UBL XML is itself the verifikation. Storage in another EU country permitted under 7 kap. 3a § with Skatteverket notification. From 1 July 2024 paper kvitton may be destroyed once correctly scanned.
+
+## Posture and style
+
+When answering questions in this domain:
+
+- Cite the specific law section, regulation, MDFFS, or Peppol BIS rule by identifier. "BR-CO-15", "SE-R-011", "BFL 7 kap. 1 §", "Lag 2018:1277 §4". Vague answers signal stale knowledge.
+- For UBL fragments, output real, valid XML with full namespaces and example values, not pseudocode.
+- For build-vs-buy or vendor selection, give numbers, €/SEK, monthly minimums, per-document costs, certification fee tiers, break-even volume, not adjectives.
+- When a regulatory date is involved, distinguish (a) hard EU deadline, (b) currently-known Swedish proposal, (c) speculation. The user is technically sophisticated and is making product decisions; mistaking speculation for binding fact is the worst possible failure mode.
+- Be willing to say "the spec is currently in flux", Peppol BIS 4.0 / PINT convergence, the DIGG → Upphandlingsmyndigheten / PTS reorganisation, the Dir. 2026:9 outcome, and the post-ViDA national mandate landscape are all moving targets in 2026–2027.
\ No newline at end of file
diff --git a/.claude/skills/swedish-e-invoicing/references/consumer-and-b2c.md b/.claude/skills/swedish-e-invoicing/references/consumer-and-b2c.md
new file mode 100644
index 00000000..32fc62c0
--- /dev/null
+++ b/.claude/skills/swedish-e-invoicing/references/consumer-and-b2c.md
@@ -0,0 +1,115 @@
+# Consumer E-Faktura Ecosystem (B2C)
+
+The B2C side of Swedish e-invoicing **runs on completely different rails from Peppol** and must be implemented separately. This reference covers Bankgirot's e-faktura privat, Kivra digital mailbox, Min Myndighetspost, and how a Swedish accounting/fintech product should approach B2C invoicing.
+
+## Bankgirot e-faktura privat, the bank rail
+
+E-faktura privat distributes invoices directly into Swedish individuals' internet bank inboxes. **Volume hit a record 168.9 million e-invoices to private individuals in 2024** (Bankföreningen).
+
+### Connection process
+
+Senders connect via **Anslutningsärende** (Standard or Express track) using the **EFA / e-giroformat**. Recipients identify themselves through **Anmälningsärende** in their own bank, selecting which senders to receive from.
+
+Bank "license" fees ~1,000 SEK/yr per bank. Transaction fees per document negotiated.
+
+### Bank participants
+
+All major Swedish banks participate:
+
+- Swedbank
+- Handelsbanken
+- Nordea
+- SEB
+- Länsförsäkringar Bank
+- ICA Banken
+- SBAB
+- Danske Bank
+- Skandia
+- Sparbankerna (the network of independent savings banks)
+
+### Volume trajectory
+
+| Year | Volume |
+|---|---|
+| 2009 | 35M |
+| 2010 | 60M |
+| 2022 | 160M |
+| **2024** | **168.9M** |
+
+Growth has flattened as Kivra has captured incremental volume.
+
+## Kivra, the digital mailbox
+
+Kivra is the **de facto digital mailbox in Sweden**. Numbers (April 2026):
+
+- **6+ million users** (~70% of Swedish adults).
+- 50,000+ corporate senders.
+- **532+ million dispatches in 2024**.
+- 99% open rate.
+- 200,000+ companies and associations as recipients.
+
+### Ownership
+
+41an Invest (Karl-Johan Persson + Stefan Krook), FAM, with SEB minority.
+
+### Capabilities
+
+- Invoice delivery + storage.
+- Tink-based PISP payments and Swish integration (one-tap pay from inbox).
+- Receipts, contracts, official mail.
+- Per-document pricing typically **3–5 SEK**.
+
+### API integration
+
+Kivra exposes a REST API for tenant senders. Visma Autoinvoice exposes Kivra-routing via its `B2CSE` service flag, viable shortcut for early product launches.
+
+## Min Myndighetspost
+
+DIGG-operated digital mailbox for government communications. Significantly lower adoption than Kivra. Mostly used for tax-related correspondence. Not a primary channel for commercial invoicing.
+
+## Consumer rails vs Peppol, the architectural distinction
+
+| Dimension | Peppol (B2B/B2G) | Bank rails / Kivra (B2C) |
+|---|---|---|
+| Format | UBL 2.1 (EN 16931) | EFA / e-giroformat / proprietary JSON |
+| Identifier | Peppol-ID (orgnr) | Personnummer / bank account |
+| Routing | SMP/SML/AS4 | Bank backend / Kivra API |
+| Onboarding | Recipient publishes in SMP | Recipient consents in their bank/Kivra |
+| Discovery | Peppol Directory | Bank-side recipient lookup or Kivra API |
+| Payment | OCR/Bankgiro/Plusgiro/IBAN | One-tap from bank/Kivra (Swish/PISP) |
+| Cost per doc | 3–3.50 SEK | 3–5 SEK (Kivra), 1–3 SEK (bank) |
+
+## Bankgirot and Plusgirot, ownership
+
+- **Bankgirot** (BGC, founded 1959) is jointly owned by SEB, Swedbank, Handelsbanken, Danske Bank, Nordea, Länsförsäkringar Bank and SkandiaBanken.
+- **Plusgirot** is owned by Nordea (acquired 2002 from Posten). A Plusgiro number is a real Nordea bank account, unlike Bankgiro which is alias-routing.
+- Both joined Bankgirot membership in 2002 for interbank deposits.
+
+## Implementation strategy for a new Swedish accounting product
+
+To support consumer (B2C) invoicing, a Swedish accounting platform needs **two parallel integrations** beyond Peppol:
+
+1. **Bankgirot e-faktura privat**, via a Certified Technical Distributor (CTD) or directly. CTD route is faster (no per-bank license negotiations) but adds intermediary cost.
+2. **Kivra**, commercial agreement plus REST API integration. Volume-tier pricing.
+
+**Shortcut:** **Visma Autoinvoice exposes both via its `B2CSE` service flag and Kivra-routing**. Acceptable for MVP / early launch; migrate to direct integration once volume justifies cost.
+
+**Routing logic** the product must implement:
+
+```
+if recipient is org → Peppol BIS Billing 3
+elif recipient has Kivra registered → Kivra API
+elif recipient has bank e-faktura registered → Bankgirot e-faktura privat
+elif recipient prefers email → PDF + email (BGC's Stora Inbetalningskortet legacy or own)
+else → paper postal (8.25–20 SEK)
+```
+
+Most B2C-heavy senders end up using Kivra preferentially because of higher engagement (99% open rate), but bank e-faktura still dominates recurring/predictable invoices (utilities, telecom, mortgages).
+
+## Authoritative source list
+
+- Bankföreningen e-faktura statistics: https://www.bankforeningen.se
+- Kivra business/sender info: https://kivra.se/foretag
+- Bankgirot e-faktura privat: https://www.bankgirot.se/tjanster/e-faktura-privat/
+- Min Myndighetspost: https://www.minmyndighetspost.se
+- Visma Autoinvoice B2CSE flag: https://documentation.autoinvoice.visma.com/integration-guide/invoice-sending/invoice-routing/
\ No newline at end of file
diff --git a/.claude/skills/swedish-e-invoicing/references/european-mandates.md b/.claude/skills/swedish-e-invoicing/references/european-mandates.md
new file mode 100644
index 00000000..39bc08f9
--- /dev/null
+++ b/.claude/skills/swedish-e-invoicing/references/european-mandates.md
@@ -0,0 +1,129 @@
+# European E-Invoicing Mandates, Comparison and ViDA Timeline
+
+This reference compares Sweden's likely trajectory to the mandates already enacted or pending in other EU member states, and lays out the binding ViDA cross-border timeline.
+
+## ViDA, the binding EU floor
+
+**VAT in the Digital Age** package adopted by ECOFIN on 11 March 2025; in force 14 April 2025; transposition deadline 31 December 2026.
+
+| Date | Obligation |
+|---|---|
+| **14 Apr 2025** | Member states may mandate domestic B2B e-invoicing without Article 395 derogation, provided EN 16931–based; recipient consent abolished |
+| **1 Jul 2030** | **Mandatory structured e-invoicing + Digital Reporting Requirements (DRR) for cross-border intra-EU B2B**; recapitulative VIES statements abolished; invoice issuance ≤10 days after chargeable event |
+| **1 Jan 2035** | Pre-existing national clearance regimes (IT/FR/PL/RO/HU/ES) must align to the EU DRR standard |
+
+**Sweden has no pre-existing CTC, so Sweden does NOT get the 2035 grandfather clause.** Any new domestic mandate must be EN 16931–compliant by design.
+
+## Country-by-country mandate status (April 2026)
+
+### Italy, centralised CTC clearance
+
+- **Sistema di Interscambio (SDI)**, government clearance hub.
+- Format: **FatturaPA**.
+- Live for B2B since 1 January 2019. Cross-border via SDI from 1 July 2022. Forfettari fully included in 2024.
+- Pre-clearance: every invoice routed through SDI before reaching the buyer.
+- **EU derogation extended to 31 December 2027.**
+- Penalties: 90–180% of VAT.
+- Archive: 10 years.
+- The "old" model that ViDA's 2035 alignment deadline forces to harmonise.
+
+### France, Y-model (Plateforme Agréée + PPF directory)
+
+- Plateforme Agréée (ex-PDP, "Partenaire de Dématérialisation Privée") + Portail Public de Facturation (PPF) as central directory.
+- Formats: **Factur-X**, UBL, CII (multi-format permitted).
+- **1 September 2026** receive obligation for all + send obligation for large enterprises and ETI (mid-cap).
+- **1 September 2027** SMEs and micro-enterprises.
+- National Assembly rejected further postponement in April 2025.
+- DGFiP became France's Peppol Authority in 2025.
+- Hybrid: PA processes the invoice, PPF receives reporting data.
+
+### Germany, decentralised, no clearance hub
+
+- Format: **XRechnung** (UBL or CII profile) or **ZUGFeRD ≥2.0.1** (hybrid PDF/A-3 + XML).
+- **Receive obligation already live since 1 January 2025**, every German business must be able to receive an e-invoice.
+- **1 January 2027** send obligation for businesses with annual turnover >€800k.
+- **1 January 2028** all businesses send.
+- Archive period reduced 10 → 8 years (from 2025).
+- Decentralised: no government hub, no clearance.
+
+### Belgium, the ViDA template
+
+- **Decentralised 4-corner Peppol mandate, live 1 January 2026.**
+- Format: **Peppol BIS Billing 3.0 / UBL** (peppol-only).
+- Tolerance period through Q1 2026 (no penalties).
+- 5-corner e-reporting layer added from 2028.
+- Penalties: €1,500 first violation / €3,000 second / €5,000 third.
+- **This is the model Sweden will most likely mirror.**
+
+### Poland, KSeF centralised clearance
+
+- **Krajowy System e-Faktur (KSeF)**, government clearance.
+- Format: **FA(3) XML**.
+- **Phase 1 live 1 February 2026** for ~4,200 entities with turnover >PLN 200M.
+- **1 April 2026** all VAT-registered.
+- **1 January 2027** micro-enterprises.
+- Penalty-free through 2026.
+- Like Italy, a CTC model that ViDA 2035 forces to align to EU DRR.
+
+### Spain, decentralised: AEAT public + private platforms
+
+- Format: **UBL / Facturae / CII / EDIFACT** (multi-format).
+- **RD 238/2026 published 31 March 2026.**
+- **+12 months (July 2027)** for businesses with turnover >€8M.
+- **+24 months (July 2028)** all.
+- Parallel **VeriFactu** invoicing software certification, January/July 2027.
+
+### Romania, CTC (RO e-Factura)
+
+- Format: **UBL 2.1 + RO-CIUS, ANAF seal**.
+- **B2B mandatory 1 July 2024.**
+- **B2C added 1 January 2025.**
+- Pre-clearance to be removed January 2026 to align with ViDA.
+
+### Norway, proposed mandatory 2028
+
+- Format: **Peppol BIS 3 / EHF**.
+- **Mandatory B2B 1 January 2028 (proposed).**
+- The Nordic peer pressure factor: a 2028 Norwegian mandate makes it implausible that Sweden would wait beyond 2030.
+
+## Sweden's likely trajectory
+
+Sweden has **20+ years of Peppol/SFTI infrastructure**, B2G mandatory since 2019, and DIGG already accredited as Peppol Authority. There is **zero political appetite** for an Italian-style centralised clearance hub, the existing decentralised infrastructure works, has proven low-friction, and aligns with EU peer countries (Belgium, Norway, Germany).
+
+**Realistic trajectory:**
+
+1. **Now → 30 November 2027**, Dir. 2026:9 inquiry runs. Skatteverket's preferred model (decentralised Peppol + DRR layer) is articulated.
+2. **2028**, Lagrådsremiss and proposition. Likely model: Belgium-style Peppol 4-corner B2B, plus a 5-corner DRR layer where Skatteverket becomes Corner 5.
+3. **2029–2030**, First domestic obligations. Likely: receive obligation first (all VAT-registered), then send obligation phased by entity size mirroring Germany's 2025→2027→2028 rollout.
+4. **1 July 2030**, ViDA cross-border B2B obligation kicks in regardless of domestic timeline. Sweden is bound.
+5. **2031–2032**, Full domestic mandate live including DRR layer.
+
+The single most important date to monitor is **30 November 2027** (Dir. 2026:9 final report). Architectural decisions made before then should preserve optionality between (a) pure Peppol 4-corner with no central reporting, (b) Peppol + DRR 5-corner, and (c) the unlikely-but-possible centralised clearance fallback.
+
+## Cross-border invoicing through Peppol, practical implications
+
+For a Swedish supplier invoicing into a mandate country today:
+
+| Destination | Current method | After 1 July 2030 |
+|---|---|---|
+| **Belgium** (since Jan 2026) | Peppol BIS Billing 3 | Same (Peppol is the format) |
+| **Italy** | Peppol→SDI bridge via service provider, or direct SDI submission | Aligned to EU DRR by 2035 |
+| **France** | Peppol→PA bridge after 1 Sep 2026 | DRR via PA / PPF |
+| **Germany** | XRechnung via Peppol or direct | XRechnung continues, DRR added |
+| **Poland** | Peppol→KSeF bridge | Aligned to EU DRR by 2035 |
+| **Romania** | Peppol→RO e-Factura bridge | Aligned to EU DRR by 2035 |
+
+**Operational implication for a Swedish accounting product:** by 2027, customers will increasingly expect "send invoice anywhere in EU" to just work. Multi-mandate routing is a hard capability, not an enterprise add-on. **Storecove or Pagero are the realistic outsourcing options** for multi-mandate send; building per-country yourself is uneconomic until very high volume.
+
+## Authoritative source list
+
+- ViDA package adoption: https://taxation-customs.ec.europa.eu/news/adoption-vat-digital-age-package-2025-03-11_en
+- ViDA Wikipedia summary (kept current): https://en.wikipedia.org/wiki/VAT_in_the_Digital_Age
+- Belgium 2026 mandate: https://edicomgroup.com/blog/belgium-will-make-b2b-electronic-invoice-mandatory
+- France PA/PPF model: https://www.impots.gouv.fr (DGFiP)
+- Germany BMF ordinance: https://www.bundesfinanzministerium.de
+- Italy SDI: https://www.fatturapa.gov.it
+- Poland KSeF: https://www.podatki.gov.pl/ksef
+- Norway 2028 proposal: https://www.regjeringen.no
+- Comarch country trackers: https://www.comarch.com/trade-and-services/data-management/legal-regulation-changes/
+- EC eInvoicing Country Sheets: https://ec.europa.eu/digital-building-blocks/sites/spaces/DIGITAL/pages/467108902/eInvoicing+in+Sweden
\ No newline at end of file
diff --git a/.claude/skills/swedish-e-invoicing/references/implementation-guide.md b/.claude/skills/swedish-e-invoicing/references/implementation-guide.md
new file mode 100644
index 00000000..31f86ee5
--- /dev/null
+++ b/.claude/skills/swedish-e-invoicing/references/implementation-guide.md
@@ -0,0 +1,205 @@
+# Implementation Guide, Building Peppol into a Swedish Accounting Product
+
+This reference is the practical builder's guide. Open-source library landscape, common rejection patterns, build-vs-buy economics, validation in CI, and a concrete phased plan for a new Swedish accounting platform.
+
+## Open-source library landscape
+
+The **Java ecosystem dominates Peppol**. Most production stacks are JVM.
+
+### Java, the canonical stack
+
+- **Oxalis** (https://github.com/OxalisCommunity/oxalis), originally Norwegian. **Oxalis 6.x is end-of-life Dec 2025.**
+- **Oxalis-NG** (https://github.com/OxalisCommunity/oxalis-ng), successor, Apache 2.0. Build on this.
+- **Oxalis-AS4 7.x** (https://github.com/OxalisCommunity/oxalis-as4).
+- **Helger phase4** (https://github.com/phax/phase4), Apache 2.0 AS4 client + server. Most comprehensive alternative to Oxalis.
+- **Helger phoss-smp**, production-grade SMP server.
+- **Helger peppol-commons**, identifiers, codelists, SBDH, SMP/SML clients.
+- **Helger phive + phive-rules**, validation engine and pre-built rules (Schematron compiled to fast XSLT).
+- **Helger ph-ubl, ph-cii, ph-sbdh**, JAXB models for UBL 2.1, UN/CEFACT CII, SBDH v1.2.
+- **phase4-peppol-standalone**, Spring Boot 3 reference implementation. Template, not turn-key.
+
+Trust stores updated to **G3-only late 2025**. Verify version when integrating.
+
+### Python
+
+- **invoice-x**, UBL/CII generation.
+- **drafthorse**, Factur-X (relevant for German/French cross-border).
+- **lxml** + Schematron-via-saxon-HE for validation.
+- **No production-grade AS4**, bridge to Java via subprocess, container, or REST microservice.
+
+### JavaScript / TypeScript
+
+- **No mature library.** Generate types from UBL 2.1 XSDs (`xsdata`, `xsd2ts`, `xmlbuilder2`) and validate via Schematron-as-WASM or call out to Java. Most TS shops use Storecove or another reseller for this reason.
+
+### .NET
+
+- **`UblLib.Bis3`**, UBL Peppol BIS 3 generation/parsing.
+- Several commercial SDKs (Storecove, Pagero).
+- Microsoft Dynamics has built-in BIS 3.0 support.
+
+## Common rejection patterns, the high-yield checklist
+
+The seven failure modes that cause **80% of production rejections**:
+
+1. **BR-CO-15 rounding mismatches** between line totals and tax-inclusive totals. Always use BigDecimal/Decimal with explicit scale; round at the boundary, never in intermediate steps.
+2. **VAT category code rule violations**, mixing `S` lines with a `Z` summary, or `AE` without `VATEX-EU-AE` reason code.
+3. **Missing or malformed BT-10 BuyerReference** for Swedish public sector, each authority has its own format. Maintain a per-buyer-Peppol-ID regex map and validate at compose time.
+4. **EndpointID `schemeID` mismatch** with what's published in the receiver's SMP. Verify via Peppol Lookup Service before sending.
+5. **Date format errors**, UBL requires `YYYY-MM-DD` xs:date.
+6. **Decimal separator and locale serialisation bugs**, period only, no thousand separators, `Locale.ROOT` / `InvariantCulture`.
+7. **Swedish character encoding**, UTF-8 throughout. Many ERPs still serialise å/ä/ö with Windows-1252.
+
+Plus:
+
+- **SBDH C1 country code mandatory since January 2024.**
+- **Attachments via `cbc:EmbeddedDocumentBinaryObject` should stay under 10 MB** despite the formal 100 MB AS4 ceiling.
+- **Multi-currency requires `TaxCurrencyCode` plus a SEK-equivalent BT-111** in a second `TaxTotal`.
+- **Missing F-skatt declaration (SE-R-005)** is the single most common Swedish rejection.
+- **Forbidden PaymentMeansCode 56 / 50** instead of 30 with `SE:BANKGIRO` / `SE:PLUSGIRO`.
+
+## Validation in CI
+
+Three-layer validation, in this order:
+
+```
+[XSD] → [EN 16931 Schematron] → [PEPPOL-EN16931-UBL.sch with SE-R-* overlay]
+```
+
+**Run all three on every UBL artifact in CI.** Use Helger phive-rules or run Schematron via Saxon-HE.
+
+```bash
+# Example: Helger CLI
+java -jar phive-rules-peppol-billing-3-cli.jar \
+ --rule "urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0" \
+ invoice.xml
+```
+
+**Validate at three points** in your pipeline:
+1. Immediately after UBL generation locally, fail fast.
+2. Before handoff to the Access Point, last chance before AS4 transmission.
+3. On receive in your inbound flow before bookkeeping, catches malformed inbound from less-strict APs.
+
+Many AP rejections happen post-send when the receiver's MLR comes back hours later, front-load validation aggressively.
+
+### Test environments
+
+- **Peppol Test Network**, `acc.edelivery.tech.ec.europa.eu` SML zone. Free for OpenPeppol members.
+- **Helger Peppol Practical**, https://peppol.helger.com, REST + UI validator.
+- **Storecove peppolvalidator.com**, error code lookup.
+- **EC DG GROW eInvoicing validator**, https://itb.ec.europa.eu/invoice
+- **Norwegian validator**, https://anskaffelser.no/verktoy/validator (also useful for Sweden).
+- **DIGG testbädd**, https://www.digg.se/digitala-tjanster/peppol/peppol-testbadd
+
+## Build vs buy, the economic break-even
+
+**Reseller cost** ~€0.10/invoice (mid-volume Storecove) vs. **own-AP fixed cost** ~€30k/year (membership + cert + ops + staff time).
+
+```
+break-even = €30,000 / €0.10 = 300,000 invoices/year
+ ≈ 3,000–5,000 active SME customers × 50–100 invoices/month
+```
+
+**For receive there is no economic case to build initially**, Storecove free receive or own Oxalis-NG on a small VPS dominate.
+
+**For send, only build above ~25k invoices/month sustained** (i.e. ~300k/year). Below that, reseller is cheaper, faster, multi-mandate, and lower ops burden.
+
+## The reseller landscape compared
+
+| Reseller | Per-doc | Multi-mandate | DX | Sandbox | Best for |
+|---|---|---|---|---|---|
+| **Storecove** | €0.05–€0.30 | Excellent (Peppol + IT SDI + FR PA + BE + DE + PL KSeF + DBNAlliance) | Single REST API, OpenAPI spec | Free 30-day | Embedding in ERP/SaaS |
+| **Pagero (TR)** | EUR 0.20–0.80 + €5–20k/yr | Excellent | Multiple APIs, enterprise-flavoured | Yes | Large enterprise |
+| **InExchange** | SEK 1–5 + 200–400/mo | Nordic | REST | Yes | SE-only SME, Visma ecosystem |
+| **Maventa (Visma)** | SEK 0.50–3 | Nordic+ | REST + SOAP | Yes | Visma ecosystem |
+| **Galaxy Gateway, Babelway, SBSCon, Comarch, Edicom, Sovos, Avalara, Tradeshift, Basware, Seeburger, Esker** | Various | Excellent | Enterprise-tier | Varies | Multi-mandate enterprise |
+
+## Recommended stack for a new Swedish accounting platform
+
+```
+Application core (bookkeeping engine, UI, API)
+ → typed UBL/EN 16931 generator (ph-ubl JAXB / xsdata-Python / UblLib.Bis3)
+ → local Schematron validator (peppol-bis-invoice-3 + phive-rules)
+ → split path:
+ RECEIVE: own Oxalis-NG AP (€100/mo Hetzner + €4,400 yr-1 OpenPeppol fees)
+ SEND: Storecove API (until ~25k invoices/month, then own phase4 AP)
+```
+
+This hybrid is the dominant strategy:
+
+- **Oxalis-NG receive on day one** is open-source-friendly, scales linearly without per-doc fees, and gives genuine "native Peppol receive" differentiation that incumbents (white-labelling Crediflow/InExchange) cannot match without rebuilding their stack.
+- **Storecove send** handles Belgium 2026, France 2026 PA flow, Italy SDI, Germany XRechnung, Poland KSeF in one API, you don't want to be re-implementing FatturaPA.
+- **Migrate send to own AP only when volume justifies it**, likely 2028–2029 at the earliest for an early-stage product.
+
+## Critical UX features
+
+1. **Per-buyer BT-10 BuyerReference regex map** for the top 200 Swedish public buyers. Validate at compose time. Prevents 30-day public-sector payment delays.
+2. **Free Peppol address out of the box** for every customer, major customer-acquisition lever in a market where competitors charge for Peppol setup.
+3. **Inbound triage UI**, parse incoming UBL, show structured fields, propose BAS posting based on supplier history and item descriptions, await user approval.
+4. **Multi-mandate send routing**, automatically route based on recipient country (`cbc:Country/cbc:IdentificationCode`) and recipient identifier scheme.
+
+## Phased plan for a new product (12 months)
+
+### Phase 0, today (Month 0)
+
+- Join OpenPeppol as End User (€650 sign-up + €1,250/yr) for forum access and early-warning on spec changes.
+- Register a Peppol participant ID for the company itself for dogfooding.
+- Set up CI with Helger phive-rules.
+
+### Phase 1, Months 1–3
+
+- UBL generator with full Peppol BIS Billing 3 + Sweden CIUS rules (SE-R-* including F-skatt).
+- Storecove sandbox for outbound test.
+- Oxalis-NG TEST environment for inbound test.
+- Schematron in CI on every UBL output.
+- BT-10 regex map for top 100 Swedish myndigheter.
+
+### Phase 2, Months 4–6
+
+- Become Candidate Service Provider (AP-only) with OpenPeppol (~€4,400 one-off + €3,350/year ongoing).
+- Pass Conformance Test Suite.
+- Sign Service Provider Agreement with DIGG (free).
+- Migrate to native Oxalis-NG receive.
+- Marketing message: "your customers email PDFs, your suppliers send Peppol e-invoices, both arrive in your inbox."
+
+### Phase 3, Months 7–12
+
+- Multi-mandate readiness for BE/DE/FR/PL/RO destinations through Storecove.
+- Per-customer compliance dashboard.
+- Begin SMP work (€2,200 + €5,000/yr SMP-only or upgrade to AP+SMP S1).
+
+### Phase 4, Year 2+
+
+- Switch send to own phase4 AP when monthly volume crosses ~25,000.
+- Pre-build Skatteverket DRR ingestion behind feature flag for July 2030 activation.
+- Pivot on SOU 2027 (due 30 November 2027), adjust architecture if Sweden chooses non-Peppol model.
+
+**Total go-live cost** for a credible, differentiated, open-source native-Peppol Swedish bookkeeping product: **approximately €10–15k plus 3 months engineering**.
+
+## Strategic positioning vs incumbents
+
+The competitive landscape has a hole.
+
+- **Visma eEkonomi, Fortnox, Bokio, SpeedLedger, Björn Lundén** all outsource their Peppol layer to Crediflow or InExchange/Maventa. None differentiate on Peppol-native architecture.
+- **The 3.00–3.50 SEK per outbound markup** these vendors charge has a baked-in reseller cost, building native eliminates that markup AND removes dependency risk now visible after the Pagero→Thomson Reuters acquisition.
+- **Native Peppol receive as a free out-of-the-box feature**, every customer gets a Peppol address by default, every supplier can send them invoices for free, is a brutal customer acquisition anchor in a market where the SMB end is underserved.
+- **The open-source angle is force multiplier**: publishing the UBL generator on GitHub under BSD/MIT earns trust with bookkeeping/Linux-friendly customers without surrendering the moat, which lives in the bookkeeping engine and UX, not the XML serialiser.
+
+Three forces converge to make this strategically valuable:
+
+1. **B2G compliance has been mandatory since April 2019**, any customer with public-sector revenue is a non-starter without native Peppol.
+2. **Large-enterprise customers** (Volvo, Ericsson, IKEA-supply, ICA, plus all Belgian/German/French subsidiaries hitting Swedish suppliers from 2026) increasingly require Peppol from suppliers.
+3. **ViDA cross-border B2B mandate of 1 July 2030 is non-negotiable**, plus the plausible domestic mandate window of 2029–2031.
+
+The window to build with this advantage is the next **18–24 months** before incumbents finish their own native-Peppol projects.
+
+## Authoritative source list
+
+- Oxalis-NG: https://github.com/OxalisCommunity/oxalis-ng
+- Helger phase4: https://github.com/phax/phase4
+- peppol-commons: https://github.com/phax/peppol-commons
+- Phive-rules: https://github.com/phax/phive-rules
+- peppol-bis-invoice-3: https://github.com/OpenPEPPOL/peppol-bis-invoice-3
+- Storecove docs: https://www.storecove.com/docs/
+- DIGG Peppol testbädd: https://www.digg.se/digitala-tjanster/peppol/peppol-testbadd
+- Peppol Testbed: https://peppol.org/tools-support/testbed/
+- OpenPeppol membership: https://peppol.eu/who-is-who/openpeppol-membership/
\ No newline at end of file
diff --git a/.claude/skills/swedish-e-invoicing/references/legal-and-regulatory.md b/.claude/skills/swedish-e-invoicing/references/legal-and-regulatory.md
new file mode 100644
index 00000000..d2042452
--- /dev/null
+++ b/.claude/skills/swedish-e-invoicing/references/legal-and-regulatory.md
@@ -0,0 +1,161 @@
+# Legal and Regulatory Framework, Swedish E-Invoicing
+
+## Swedish primary legislation
+
+### Lag (2018:1277) om elektroniska fakturor till följd av offentlig upphandling
+
+The operative statute. SFS 2018:1277, in force **1 April 2019**, amended SFS 2023:212 to update VAT-law cross-references to ML 2023:200.
+
+- **§1 Scope.** Covers all invoices issued as a consequence of procurement under LOU 2016:1145, LUF 2016:1146, LUK 2016:1147 and LUFS 2011:1029. The trigger is "consequence of public procurement", not the identity of buyer or seller.
+- **§2 Definition.** An e-invoice is an invoice issued, sent and received in a *structured electronic format that allows automatic and electronic processing*. **PDF and scanned paper are explicitly excluded.** Image-based formats fail the definition regardless of how they are transmitted.
+- **§4 Standard.** EN 16931 conformance via Commission Implementing Decision (EU) 2017/1870. Parties may bilaterally agree on alternative standards.
+- **§5 Reception duty.** Contracting authorities must receive and process EN 16931 invoices.
+- **§7 Sanctions.** **DIGG can issue *vitesföreläggande* (penalty injunctions)** against non-compliant suppliers. The amount is set discretionarily.
+- **§8 Appeals.** Appeals go to allmän förvaltningsdomstol; prövningstillstånd required for kammarrätten.
+
+Source: https://www.riksdagen.se/sv/dokument-och-lagar/dokument/svensk-forfattningssamling/lag-20181277-om-elektroniska-fakturor-till_sfs-2018-1277/
+
+### Förordning (2018:1486)
+
+Designates **DIGG (Myndigheten för digital förvaltning)** as supervising authority and Sweden's Peppol Authority. Source: https://www.digg.se/kunskap-och-stod/e-handel/lag-forordning-och-foreskrifter-for-e-handel
+
+### MDFFS 2019:1 (Föreskrift om registrering i PEPPOL)
+
+In force **1 December 2019**. Requires all contracting authorities to publish themselves in Peppol's SMP (Service Metadata Publisher) registry.
+
+### MDFFS 2021:1
+
+§§12–20 require state agencies to:
+- use Peppol BIS Billing 3 for outbound invoices to other state agencies;
+- send e-invoices to non-state recipients that have consented;
+- handle inbound e-invoices in EN 16931 conformance.
+
+### Förordning (2000:606) §21f and Förordning (2003:770)
+
+Have required state agencies to handle invoices and orders electronically since 2008/2014. Per **SFS 2025:1201, regulatory authority over Förordning 2000:606 transfers from ESV to Statskontoret on 1 January 2026**.
+
+### Bokföringslag (1999:1078), archive rules
+
+Most recent consolidation: SFS 2024:342, in force **1 July 2024**. Modernised the archive regime for digital räkenskapsinformation.
+
+- **7 kap. 1 § / 7 kap. 2 §.** Räkenskapsinformation must be stored in the form in which it was created or received. **The inbound UBL XML is itself the verifikation; a printout is not.**
+- **7 kap. 2 § (post-2024).** Retention is **7 years** after the calendar year in which the financial year ended. (Reduced from the historical 10 years.)
+- **7 kap. 3 §.** Equipment to read electronic data must remain available *in Sweden* throughout retention.
+- **7 kap. 3a §.** Electronic storage in another EU country is permitted if (a) Skatteverket is notified, (b) immediate online access is granted, and (c) printouts can be produced in Sweden upon request.
+- **5 kap. 5 §.** Immutable bookkeeping, corrections are new posts, never overwrites.
+- **4 kap. 4 §.** Language: Swedish, Danish, Norwegian or English.
+- **Post-2024-07-01 change:** the prior requirement to retain paper originals for 3 years post-digitisation has been **abolished**. Paper kvitton may be destroyed once correctly scanned.
+
+### Mervärdesskattelag (2023:200), invoice content
+
+Replaces ML 1994:200 since 1 July 2023.
+
+- **2 kap. 9–10 §§.** Defines the e-invoice consistent with Article 217 of Directive 2006/112/EC.
+- **17 kap.** Mandatory invoice content, implements Article 226 of the VAT Directive.
+- **SKVFS 2024:16.** Simplified invoices (förenklad faktura).
+- **No qualified electronic signature is required.** Authenticity and integrity are ensured via "business controls creating a reliable audit trail" per Article 233 of Directive 2006/112/EC. The Peppol AS4 message-level signing between Access Points is sufficient.
+
+### Skatteverket online audit rights, 1 April 2026
+
+Pending legislation removed the historical ban on remote audit access. **From 1 April 2026, Skatteverket has expanded "online audit" rights**, direct read access to taxpayers' digital accounting/VAT records during audit. **This is access-rights legislation, not a SAF-T submission mandate.** Sweden does not yet require periodic SAF-T submission.
+
+## EU framework
+
+### Directive 2014/55/EU and EN 16931
+
+- Directive 2014/55/EU, transposition deadline 27 November 2018.
+- Commission Implementing Decision (EU) 2017/1870 anchors EN 16931 as the European e-invoicing semantic.
+- **EN 16931-1**: syntax-agnostic semantic data model, BT-1…BT-150+ business terms, BG-1…BG-25 business groups.
+- **EN 16931-2**: binds two normative syntaxes: **UBL 2.1** (ISO/IEC 19845:2015) and **UN/CEFACT CII** (D16B).
+- Peppol BIS Billing 3.0 is a **CIUS** (Core Invoice Usage Specification) of EN 16931 in UBL syntax only. CII is permitted at the Peppol layer but not in BIS Billing 3.0.
+
+### ViDA, VAT in the Digital Age
+
+Adopted by ECOFIN on **11 March 2025** as three legal acts:
+- **Council Directive (EU) 2025/516**
+- **Regulation (EU) 2025/517**
+- **Implementing Regulation (EU) 2025/518**
+
+Published in OJEU 25 March 2025, in force **14 April 2025**, transposition deadline **31 December 2026**.
+
+Binding dates relevant for Sweden:
+
+| Date | Obligation |
+|---|---|
+| 14 Apr 2025 | Member states may mandate domestic B2B e-invoicing without Article 395 derogation, provided EN 16931–based; recipient consent abolished |
+| 1 Jul 2030 | **Mandatory structured e-invoicing + Digital Reporting Requirements (DRR) for cross-border intra-EU B2B**; recapitulative VIES statements abolished; invoice issuance ≤10 days after chargeable event |
+| 1 Jan 2035 | Pre-existing national clearance regimes (IT/FR/PL/RO/HU/ES) must align to the EU DRR standard |
+
+**Sweden has no pre-existing CTC, so Sweden does NOT get the 2035 grandfather clause.** Any new domestic mandate Sweden builds post-2025 must already be EN 16931–compliant by design.
+
+## Swedish authorities
+
+### DIGG (Myndigheten för digital förvaltning)
+
+- Sweden's Peppol Authority.
+- Regulator under §7 of Lag 2018:1277.
+- Issues binding föreskrifter MDFFS 2019:1 and MDFFS 2021:1.
+- DIGG's own Peppol-ID: `0007:2021006883`.
+- **Reorganisation alert:** Per regeringsbeslut Fi2025/01826, DIGG's e-handel/Peppol functions transfer to **Upphandlingsmyndigheten on 1 July 2026**. DIGG itself is to be merged into PTS by 1 January 2027 forming a new digitalisation agency. Adjust regulatory monitoring accordingly.
+
+### Skatteverket
+
+- Receives e-invoices via Peppol at `0007:2021005448`.
+- Publicly **in favour** of mandatory domestic B2B e-invoicing and transaction-based reporting.
+- Ran a public consultation June–July 2025 on three models (SAF-T, clearance, post-audit-with-real-time-reporting).
+- Estimates **SEK 10–20 billion/year** in business savings if Sweden mandates domestic e-invoicing.
+- Sektionschef Björn Erling has explicitly endorsed Peppol as the future Swedish standard.
+
+### ESV (Ekonomistyrningsverket) and Statskontoret
+
+- ESV historically drove state e-invoicing since 2008 (Förordn. 2000:606 §21f).
+- Per SFS 2025:1201, regulatory authority transfers to **Statskontoret on 1 January 2026**.
+
+### SFTI (Single Face To Industry)
+
+- Collaboration between SKR (Sveriges Kommuner och Regioner), DIGG, Upphandlingsmyndigheten and Kammarkollegiet.
+- Sets the recommended Swedish standards.
+- **From 1 July 2025: SFTI ESAP 6 (EDIFACT) was removed; Svefaktura 1.0/2.0 and SFTI Fulltextfaktura are formally deprecated; Peppol BIS Billing 3 is the only strategic format.**
+
+### Government inquiry Dir. 2026:9, the single most important date
+
+**Kommittédirektiv Dir. 2026:9** "Moderniserad och brottsförebyggande hantering av mervärdesskatt" was issued **5 February 2026** with a final report deadline of **30 November 2027**.
+
+The inquiry will determine:
+- whether Sweden mandates domestic B2B e-invoicing;
+- whether Sweden adopts transaction-based reporting (DRR-style or otherwise);
+- the architectural model (decentralised Peppol vs. centralised clearance vs. post-audit with real-time reporting).
+
+**Realistic Swedish trajectory:** SOU report 30 November 2027 → lagrådsremiss/proposition 2028 → first domestic obligations **2029–2030** (likely receive obligation first, send obligation phased by entity size, mirroring Germany's 2025/2027/2028 rollout). The reference design Sweden will mirror is **Belgium's 2026 decentralised Peppol 4-corner model**, eventually augmented with a 5-corner DRR layer where Skatteverket becomes Corner 5.
+
+## Penalties and the B2G/B2B/B2C distinction
+
+| Segment | Status (April 2026) | Format | Penalty |
+|---|---|---|---|
+| **B2G** (consequence of public procurement) | Mandatory since 1 April 2019 | EN 16931 / Peppol BIS Billing 3 | DIGG vitesföreläggande, discretionary fine; practical risk also: lost public-sector business |
+| **B2G** (state-to-state, state-to-private with consent) | Mandatory | Peppol BIS Billing 3 | Internal compliance |
+| **B2B** | **Voluntary** | Free choice (Peppol BIS dominant; legacy Svefaktura tolerated bilaterally) | None |
+| **B2C** | Voluntary | Bank rails / Kivra (not Peppol) | None |
+
+## GDPR for e-invoicing
+
+- Invoices to natural persons and sole proprietors contain personal data.
+- **DIGG recommends sole proprietors use a GLN identifier (ICD `0088`) rather than a personnummer-based Peppol-ID (`0007`)** to minimise exposure of the personnummer in routing metadata visible across the network.
+- Lawful basis is Article 6(1)(c) (legal obligation under BFL/ML/Lag 2018:1277).
+- The 7-year BFL retention overrides Article 5(1)(e) storage limitation.
+- **Access points act as Article 28 processors.** DPAs are required between sending business and its AP, and between recipient and its AP.
+- Cross-border Peppol routing within EEA is not a Chapter V transfer; care is needed if an AP routes via non-EEA infrastructure (some APs use US/UK clouds).
+- From 1 April 2026, the Skatteverket online-audit power requires architecting a "tax-auditor" role with secure read-only API access on the accounting system itself.
+
+## Authoritative source list
+
+- Lag (2018:1277): https://www.riksdagen.se/sv/dokument-och-lagar/dokument/svensk-forfattningssamling/lag-20181277-om-elektroniska-fakturor-till_sfs-2018-1277/
+- Bokföringslag (1999:1078): https://www.riksdagen.se/sv/dokument-och-lagar/dokument/svensk-forfattningssamling/bokforingslag-19991078_sfs-1999-1078/
+- DIGG e-handel laws and regs: https://www.digg.se/kunskap-och-stod/e-handel/lag-forordning-och-foreskrifter-for-e-handel
+- DIGG Peppol statistics: https://www.digg.se/digitala-tjanster/peppol/statistik-fran-peppolnatverket-
+- SFTI standards: https://sfti.se/sfti/standarder/peppolbisehandel/peppolbisbilling3.49021.html
+- Skatteverket e-faktura: https://skatteverket.se/omoss/varverksamhet/forleverantorer/efakturortillskatteverket.4.b1014b415f3321c0de2680.html
+- Skatteverket on transaction-based reporting: https://www.skatteverket.se/foretag/internationellt/transaktionsbaseradrapporteringochefakturering.4.386bd4b919276cc86c42b3f.html
+- Dir. 2026:9: https://www.regeringen.se/pressmeddelanden/2026/02/ny-utredning-om-modernare-momsregler-och-battre-verktyg-mot-momsbedragerier/
+- ViDA package: https://taxation-customs.ec.europa.eu/news/adoption-vat-digital-age-package-2025-03-11_en
+- EC eInvoicing Country Sheet for Sweden: https://ec.europa.eu/digital-building-blocks/sites/spaces/DIGITAL/pages/467108902/eInvoicing+in+Sweden
\ No newline at end of file
diff --git a/.claude/skills/swedish-e-invoicing/references/market-provider-pricing.md b/.claude/skills/swedish-e-invoicing/references/market-provider-pricing.md
new file mode 100644
index 00000000..20b416b7
--- /dev/null
+++ b/.claude/skills/swedish-e-invoicing/references/market-provider-pricing.md
@@ -0,0 +1,132 @@
+# Swedish E-Invoicing Market, Providers and Pricing
+
+This reference covers (a) which Access Points and service providers operate in Sweden, (b) how the dominant Swedish accounting platforms (Fortnox, Visma, Bokio, SpeedLedger, Björn Lundén, Hogia) wire their Peppol layers, almost all white-label, (c) per-document pricing benchmarks, (d) the post-2022 industry consolidation pattern.
+
+## Major Swedish Access Points and service providers
+
+| Provider | Status (Apr 2026) | Segment | Reach (claimed) | Notes |
+|---|---|---|---|---|
+| **Pagero** | Acquired by **Thomson Reuters Feb 2024** (~SEK 8.1B / USD 800M); now branded "ONESOURCE Pagero" | Large enterprise / global multinationals + free SME tier | 90,000 customers, 14M-company network, 75+ countries | Net sales 2023 SEK 795M (+33%); EBITA −SEK 17.4M. REST APIs (Document/Network/Signup/File/User). Quote-based pricing. Strong in global tax compliance. |
+| **InExchange (Factorum AB)** | **Visma group since ~2020**, Skövde HQ | SME / mid-market dominant | ~80M tx/yr, 60,000 customers, 800,000+ orgs | Underlying operator for **Visma Autoinvoice** and Hantverksdata Entré. 12 invoices/yr free tier. Heaviest installed Swedish SME base. |
+| **Crediflow AB** | PE-backed by **VIA Equity (2024)**; group includes OptoSweden, DocUp | Mid-market, ERP/system partner | 300,000+ companies monthly via 60+ ERPs | **Underlying AP for Fortnox, Bokio, SpeedLedger.** Group revenue ~SEK 100M. Most Swedish SaaS accounting depends on Crediflow. |
+| **Visma Autoinvoice / Maventa** | Visma Group (KKR/HG/Cinven) | Captive Visma ecosystem | Routes through Maventa AP + InExchange | Cross-border via Peppol BIS 3; converts Svefaktura 1.0, TEAPPSXML, Finvoice 3.0, VismaXML, LiinosXML, SI-UBL. **API documentation:** https://documentation.autoinvoice.visma.com/ |
+| **Tietoevry (BIX)** | Listed Finnish-Swedish | Banks, large enterprise, public sector | Certified Peppol AP since 2012 | White-labels to two of the largest Swedish banks. Strong B2C (Multichannel/Live Invoice). |
+| **Basware** | **Take-private 2022** by Accel-KKR + Long Path + Briarwood (€620M, 94.7% premium) | Large global enterprise AP automation | 700+ global customers, 170M invoices/yr | HQ Helsinki/Espoo. Strong with Hogia. |
+| **OpusCapita** | Acquired by **GEP (US) 1 July 2024** from PSG Equity | Mid/large enterprise, Nordics | 600 clients | Operates Skatteverket's free supplier portal. |
+| **Ropo Capital** | Adelis Equity-backed; acquired Colligent Inkasso (2019), Posti Messaging Scandinavia (2020) | Large invoice volumes (energy, real estate, telco) | 11,000+ Nordic customers, 170M+ docs/yr | Combines invoicing + collections. |
+| **Qvalia** | Swedish, Stockholm | SME, developer-friendly | 30+ countries, ISO 27001 | **Public, transparent EUR pricing** (see below). Best DX choice for an open-source integration. |
+| **Hogia** | Swedish | Enterprise | Own Peppol AP | **Only major SE accounting vendor with its own Peppol AP** (others white-label). Uses Basware fakturaadresser for some units. |
+| **Compello, Edicom, TrueCommerce, Tungsten Automation** | Various | Niche / enterprise / EDI |, | Minor Sweden footprint relative to top tier. |
+| **Storecove** | Dutch | Developer-first, multi-mandate API | 30+ countries | Single REST API spans Peppol + DBNAlliance + local mandates (FR, IT SDI, BE, DE, PL KSeF, etc.). 30-day free sandbox. Strong fit for ERP/SaaS embedding. |
+
+## Qvalia public pricing (EUR, as of April 2026)
+
+| Tier | Monthly EUR | Messages/mo |
+|---|---|---|
+| Free | €0 | 1 |
+| Small | €9 | 25 |
+| Medium | €39 | 100 |
+| Plus | €99 | 1,000 |
+| Plus | €249 | 2,500 |
+| Plus | €499 | 5,000 |
+| Plus | €899 | 10,000+ |
+
+Setup fee 0. Includes inbound + outbound Peppol BIS Billing 3 + EHF + multi-mandate routing. **Most transparent commercial pricing in the Swedish market**, useful as a benchmark.
+
+## SME pricing benchmarks (April 2026)
+
+| Item | Typical SME price (SEK) |
+|---|---|
+| Outbound e-invoice (sender) | **3.00–3.50** (Bokio, SpeedLedger, BL); 0–3.40 (InExchange) |
+| Inbound e-invoice | Often free; 3.50 (BL) |
+| Monthly minimum (SME platform) | 0–199 |
+| Setup/onboarding | 0 |
+| Postal fallback | 8.25–20 |
+| Kivra to consumer | ~5 |
+| Enterprise (Pagero/Basware) per-doc | Negotiated, EUR 0.10–0.50 |
+
+## How Swedish accounting platforms wire Peppol
+
+**The dominant SME accounting platforms in Sweden all white-label two intermediaries.** Fortnox, Bokio and SpeedLedger funnel through **Crediflow**. Visma eEkonomi/SPCS/Administration/Business funnel through **Visma Autoinvoice (Maventa)**, which is itself a certified Peppol AP. None operate their own Peppol AP, except Hogia.
+
+This concentration is a strategic opening for any new platform: **building native Peppol disintermediates the entire value chain** and removes a markup baked into incumbent pricing.
+
+### Fortnox
+
+- Sweden's largest cloud ERP (~500,000+ customers).
+- REST API at `https://api.fortnox.se/3/` (XML or JSON).
+- Rate limit 25 req/5s/token.
+- OAuth2 via `https://apps.fortnox.se/oauth-v1/`.
+- Key endpoints: `/3/invoices`, `/3/supplierinvoices`, `/3/supplierinvoicepayments`, `/3/invoicepayments`, `/3/supplierinvoicefileconnections` (attach UBL/PDF), `/3/supplierinvoiceaccruals`, `/3/customers`, `/3/suppliers`, `/3/articles`, `/3/vouchers`, `/3/accounts`, `/3/financialyears`, `/3/taxreductions` (ROT/RUT), `/3/noxfinansinvoices` (factoring).
+- WebSocket push API delivers `Invoices`/`SupplierInvoices`/`Vouchers`/`Customers` topics.
+- Peppol-ID auto-published in Peppol Directory for AB customers.
+- ROT/RUT housework supported natively (`HouseWork=true`, `HouseWorkType`, `HouseWorkHoursToReport`).
+
+### Visma Autoinvoice / Maventa
+
+- Cleanest Peppol developer story among Swedish platforms.
+- API docs: https://documentation.autoinvoice.visma.com/
+- REST and legacy SOAP, OAuth2 client-credentials.
+- Operator routing flags: `PEPPOL`, `INEXCHANGE`, `NEMHANDEL`, `SCAN`, `BANK`, `B2CSE`, `VISMASCANNER`.
+- The `lookup`/`finder` endpoint exposes SMP discovery.
+- `POST /v1/services/b2cse/agreement` registers a sender on the Swedish bank-based B2C rail (e-faktura privat).
+
+### Bokio
+
+- Outbound UBL Peppol BIS Billing 3 at **3 SEK per invoice** via Crediflow.
+- **B2B only** for outbound Peppol.
+- Auto-flags year-end-crossing invoices.
+- Provides "Konvertera till fakturametoden" UX, useful template for any Swedish bookkeeping product.
+
+### Björn Lundén (BL Total / Lundify)
+
+- **3.50 SEK per outbound and inbound** e-invoice.
+
+### SpeedLedger
+
+- Bank-feed centric.
+- **3 SEK per sent**.
+
+### Hogia
+
+- The only major SE accounting vendor with its own Peppol AP.
+- Owns relationships with several mid-market customers.
+
+## Industry consolidation post-2022
+
+Pattern: **bigger players are bundling tax + invoicing + AP automation + compliance reporting for enterprise**, leaving the Swedish SME and redovisningsbyrå segment as fertile ground.
+
+| Year | Event |
+|---|---|
+| 2022 | Basware take-private by Accel-KKR + Long Path + Briarwood, €620M, 94.7% premium |
+| Feb 2024 | Thomson Reuters acquires Pagero, ~SEK 8.1B / USD 800M |
+| 2024 | VIA Equity acquires Crediflow group |
+| 1 Jul 2024 | GEP (US) acquires OpusCapita from PSG Equity |
+| ~2020 | Visma Group acquires InExchange (Factorum AB) |
+| 2019–2020 | Ropo Capital acquires Colligent Inkasso, Posti Messaging Scandinavia |
+
+**Reseller dependency risk is now real**, Pagero is a TR division, Basware is PE-owned, both will eventually re-price upward. Build optionality into the stack via a clean `SendClient` abstraction with dual-vendor capability.
+
+## Choosing an Access Point partner, decision framework
+
+For a new Swedish accounting/fintech product, the practical menu:
+
+1. **Storecove**, best DX, single API across Peppol + IT SDI + FR PA + PL KSeF + BE + DE. Free 30-day sandbox. Effective rate €0.05–€0.30/invoice. **Best fit when multi-mandate is needed.**
+2. **Qvalia**, transparent EUR pricing, ISO 27001, Swedish-headquartered. Good fit for SME-only Swedish flows.
+3. **InExchange**, heaviest Swedish installed base, but partial vendor lock-in via Visma Group ownership.
+4. **Visma Autoinvoice / Maventa**, only worth it if already integrating Visma ecosystem.
+5. **Pagero / Basware**, enterprise-only, not SME-friendly post-acquisition.
+6. **Own Oxalis-NG AP**, only for receive at low volume (€100/mo Hetzner + €4,400 yr-1 OpenPeppol fees). For send, only economic above ~25k invoices/month.
+
+**Build vs buy break-even:** reseller cost of ~€0.10/invoice (mid-volume Storecove) versus own-AP fixed cost of ~€30k/year (membership + cert + ops) breaks even at **~300,000 invoices/year sent through your customers**, equivalent to ~3,000–5,000 active SME customers each sending 50–100 invoices/month. **For receive there is no economic case to build initially**, Storecove free receive or own Oxalis on a small VPS dominate.
+
+## Authoritative source list
+
+- DIGG Peppol traffic stats: https://www.digg.se/digitala-tjanster/peppol/statistik-fran-peppolnatverket-
+- Visma Autoinvoice docs: https://documentation.autoinvoice.visma.com/
+- Fortnox API: https://developer.fortnox.se/
+- Pagero compliance pages: https://www.pagero.com/compliance/regulatory-updates/sweden
+- Storecove blog/docs: https://www.storecove.com
+- Qvalia pricing: https://qvalia.com/pricing/
+- InExchange knowledge base: https://inexchange.com/en/discover
+- Skatteverket on B2G e-faktura: https://skatteverket.se/omoss/varverksamhet/forleverantorer/efakturortillskatteverket.4.b1014b415f3321c0de2680.html
\ No newline at end of file
diff --git a/.claude/skills/swedish-e-invoicing/references/peppol-bis-billing.md b/.claude/skills/swedish-e-invoicing/references/peppol-bis-billing.md
new file mode 100644
index 00000000..0f685aa3
--- /dev/null
+++ b/.claude/skills/swedish-e-invoicing/references/peppol-bis-billing.md
@@ -0,0 +1,241 @@
+# Peppol BIS Billing 3.0, Wire Format Reference
+
+## The BIS suite and document identifiers
+
+Peppol BIS Billing 3.0 is identified by:
+
+```
+cbc:CustomizationID = urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0
+cbc:ProfileID = urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+```
+
+UBL roots are `Invoice` (`urn:oasis:names:specification:ubl:schema:xsd:Invoice-2`) and `CreditNote` (`urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2`). The current Peppol POACC release is **Billing 3.0.20 (November 2025)**.
+
+The wider BIS 3.0 suite (Peppol Post-Award and adjacent profiles):
+
+| Profile | Process ID suffix | Purpose |
+|---|---|---|
+| Billing 3 | `billing:01:1.0` | Standard B2B/B2G invoice + credit note |
+| Self-Billing 3 | `selfbilling:01:1.0` | Buyer issues invoice on supplier's behalf |
+| Order Only / Ordering / Advanced Ordering / Order Agreement | `ordering:*` | Procurement order flows |
+| Despatch Advice 3 | `despatchadvice:01:1.0` | Shipment notification |
+| Catalogue 3 | `catalogue:01:1.0` | Product catalogue exchange |
+| Invoice Response (IMR, T111) | `invoiceresponse:01:1.0` | Buyer accepts/rejects invoice |
+| Message Level Response (MLR, T71) | `mlr:01:1.0` | Technical receipt confirmation |
+| **Message Level Status (MLS)** | `urn:peppol:edec:mls:1.0` | New: machine-readable processing status |
+
+**Peppol BIS 4.0 / PINT convergence** is announced for late 2025 / early 2026, track release notes at https://docs.peppol.eu/poacc/billing/3.0/bis/ before locking long-lived schemas.
+
+InvoiceTypeCode (BT-3) restricted set: `380` commercial invoice, `381` credit note (Invoice), `384` corrected invoice, `389` self-billed. CreditNoteTypeCode: `381` credit note, `396` factored credit note, `261` self-billed credit note.
+
+## Mandatory header
+
+```xml
+
+ urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+ INV-2026-00001
+ 2026-04-27
+ 2026-05-27
+ 380
+ SEK
+ SE-DEPT-42
+ ...
+
+```
+
+## Party blocks
+
+`AccountingSupplierParty` and `AccountingCustomerParty` carry:
+
+- `cbc:EndpointID` (BT-34, mandatory `schemeID`), the Peppol routing address.
+- `cac:PartyIdentification/cbc:ID`, additional business identifiers (GLN, etc.).
+- `cac:PartyName/cbc:Name`.
+- `cac:PostalAddress`, `StreetName`, `CityName`, `PostalZone`, `Country/IdentificationCode`.
+- `cac:PartyTaxScheme/cbc:CompanyID`, VAT identifier.
+- `cac:PartyLegalEntity/cbc:RegistrationName` and `cbc:CompanyID`.
+- `cac:Contact`.
+
+For Swedish entities see `swedish-cius-and-specifics.md` for the F-skatt rule, orgnr formats, and VAT prefix requirements.
+
+## VAT category codes (UNCL5305)
+
+Used in `cac:ClassifiedTaxCategory/cbc:ID` per line and `cac:TaxCategory/cbc:ID` in summary blocks.
+
+| Code | Meaning | Rate | TaxExemptionReason |
+|---|---|---|---|
+| **S** | Standard rate | >0 | No |
+| **Z** | Zero rated | 0 | No |
+| **E** | Exempt from VAT | 0 | Yes (BT-120/BT-121) |
+| **AE** | Reverse charge | 0 | Yes (`VATEX-EU-AE`) |
+| **K** | Intra-EU supply of goods/services | 0 | Yes (`VATEX-EU-IC`) |
+| **G** | Export outside EU | 0 | Yes (`VATEX-EU-G`) |
+| **O** | Outside scope of VAT | n/a | Yes (`VATEX-EU-O`) |
+| **L** | IGIC (Canary Islands) | various | Spanish use |
+| **M** | IPSI (Ceuta/Melilla) | various | Spanish use |
+
+Reverse charge example (Sweden→EU customer):
+
+```xml
+
+ AE
+ 0
+ VAT
+
+```
+
+In the summary `TaxSubtotal`:
+
+```xml
+
+ 10000.00
+ 0.00
+
+ AE
+ 0
+ VATEX-EU-AE
+ Reverse charge
+ VAT
+
+
+```
+
+## Multi-currency handling
+
+`DocumentCurrencyCode` (BT-5) drives all amounts. If it differs from the seller's VAT accounting currency:
+- Add `cbc:TaxCurrencyCode` (BT-6).
+- Add a second `cac:TaxTotal` carrying only the SEK-equivalent total tax (BT-111).
+
+```xml
+EUR
+SEK
+...
+
+ 2500.00
+ ...
+
+
+ 28750.00
+
+```
+
+## Calculation rules, the failure surface
+
+These are the rules that cause the majority of production rejections.
+
+| Rule | Constraint |
+|---|---|
+| **BR-CO-15** | `BT-112 = BT-109 + BT-110` (TaxInclusiveAmount = TaxExclusive + Tax). Canonical rounding bug. |
+| **BR-CO-13** | `BT-109 = BT-106 − BT-107 + BT-108` (TaxExclusive = LineTotal − Allowances + Charges) |
+| **BR-CO-17** | `BT-117 = round2(BT-116 × BT-119 / 100)` (per category tax = taxable × rate) |
+| **BR-S-08, BR-Z-08, BR-E-08, BR-AE-08, BR-IC-08, BR-G-08, BR-O-08** | Per-category taxable amount must reconcile to corresponding line totals + charges − allowances |
+| **BR-CO-9** | VAT identifier must start with country code prefix |
+| **BR-S-01 / BR-Z-01 / etc.** | At least one line, allowance or charge per used VAT category |
+| **PEPPOL-EN16931-R053** | Only one tax total without currency suffix |
+
+**Always do arithmetic in BigDecimal/Decimal with explicit scale.** Round at the boundary, never in intermediate steps. Force `Locale.ROOT` / `InvariantCulture` for serialisation. Document totals must be exactly 2 decimals; price amounts (BT-146/BT-148) are unbounded.
+
+Belgium's 2026 mandate disallows line-by-line VAT rounding; Sweden currently allows it but may not for long.
+
+## Allowances and charges
+
+Document level via `cac:AllowanceCharge`:
+
+```xml
+
+ false
+ 95
+ Volume rebate
+ 100.00
+
+ S
+ 25
+ VAT
+
+
+```
+
+UNCL5189 reason codes (allowance) include: 41 Bonus for works ahead of schedule, 60 Manufacturer's consumer discount, 95 Discount, 100 Special rebate, 102 Fixed long term, 103 Temporary, 104 Standard. UNCL7161 reason codes (charge) include: AA Advertising, AAA Telecommunication, ABK Miscellaneous, FC Freight charge, IN Insurance, SH Shipping and handling.
+
+## Line items
+
+```xml
+
+ 1
+ 10
+ 5000.00
+
+ Consulting hours
+
+ S
+ 25
+ VAT
+
+
+
+ 500.00
+
+
+```
+
+`unitCode` follows UN/ECE Recommendation 20 (`EA` each, `HUR` hour, `KGM` kilogram, `MTR` metre, `LTR` litre, `DAY` day, `MON` month, `C62` "one", used for dimensionless services).
+
+## Document totals
+
+```xml
+
+ 10000.00
+ 9900.00
+ 12375.00
+ 100.00
+ 0.00
+ 0.00
+ 0.00
+ 12375.00
+
+```
+
+## Attachments
+
+Via `cac:AdditionalDocumentReference` with `cac:Attachment/cbc:EmbeddedDocumentBinaryObject` (base64) or `cac:ExternalReference/cbc:URI`. Inline attachments should stay under 10 MB despite the formal 100 MB AS4 ceiling, many access points reject larger payloads in practice.
+
+```xml
+
+ timesheet-april-2026.pdf
+ Detailed timesheet
+
+ JVBERi0xLjQK...
+
+
+```
+
+## Validation stack
+
+Three layers in this order:
+
+1. **XSD**, UBL 2.1 schemas. Catches structural errors. Source: https://docs.oasis-open.org/ubl/os-UBL-2.1/UBL-2.1.html
+2. **EN 16931 Schematron**, CEN/TC 434 official artefacts (`EN16931-UBL-validation.sch`). Catches BR-* business rules and BR-CO-* calculation rules.
+3. **`PEPPOL-EN16931-UBL.sch`**, Peppol overlay with country-specific rules. SE-R-* (Sweden), NO-R-* (Norway), IT-R-* (Italy), DE-R-* (Germany), NL-R-* (Netherlands), DK-R-* (Denmark).
+
+Authoritative GitHub repo: **https://github.com/OpenPEPPOL/peppol-bis-invoice-3** with releases on a May/November cadence.
+
+Validators to integrate:
+- **Helger Peppol Practical**, https://peppol.helger.com, REST + UI, runs phive-rules.
+- **Storecove peppolvalidator.com**, https://peppolvalidator.com, error code lookup.
+- **EC DG GROW eInvoicing validator**, https://itb.ec.europa.eu/invoice, official EC validator.
+- **Norwegian validator**, https://anskaffelser.no/verktoy/validator (also useful for Sweden).
+- **DIGG testbädd**, https://www.digg.se/digitala-tjanster/peppol/peppol-testbadd
+
+Validate at **three points** in your pipeline: (1) immediately after UBL generation locally; (2) before handoff to the Access Point; (3) on receive in your inbound flow before bookkeeping. Many AP rejections happen post-send when the receiver's MLR comes back hours later.
+
+## Authoritative source list
+
+- Peppol BIS Billing 3.0 specification: https://docs.peppol.eu/poacc/billing/3.0/bis/
+- UBL 2.1 syntax tree: https://docs.peppol.eu/poacc/billing/3.0/syntax/ubl-invoice/
+- Self-billing: https://docs.peppol.eu/poacc/self-billing/3.0/bis-sb/
+- Peppol document types index: https://www.peppol.nu/knowledge-base/peppol-document-types-standards/
+- OpenPEPPOL repo: https://github.com/OpenPEPPOL/peppol-bis-invoice-3
+- Validator with error code lookup: https://peppolvalidator.com/peppol-validation-errors
\ No newline at end of file
diff --git a/.claude/skills/swedish-e-invoicing/references/peppol-network.md b/.claude/skills/swedish-e-invoicing/references/peppol-network.md
new file mode 100644
index 00000000..d19eebbe
--- /dev/null
+++ b/.claude/skills/swedish-e-invoicing/references/peppol-network.md
@@ -0,0 +1,172 @@
+# Peppol Network Architecture, AS4, SMP, SML, PKI
+
+## The four-corner model
+
+Standard Peppol routing:
+
+```
+[C1 Sender] → [C2 Sending AP] → [C3 Receiving AP] → [C4 Receiver]
+ ERP ERP
+ ─── Peppol network ───
+```
+
+Only **C2↔C3** is on-network. C1↔C2 and C3↔C4 are local integrations (REST API, SFTP, file watcher, ERP plugin) chosen by each AP. Sending and receiving APs may belong to different organisations or to the same provider; they may also be the same AP (intra-network delivery).
+
+ViDA introduces the **five-corner model** for cross-border B2B reporting from 1 July 2030: the tax administration becomes Corner 5 receiving DRR data in parallel with C3.
+
+## SML, Service Metadata Locator
+
+The SML is the centralised DNS service. Operated by **OpenPeppol AISBL** (insourced from EC DG DIGIT during 2024–2025).
+
+Lookup algorithm (migrated from CNAME/MD5 to **NAPTR/SHA-256** during 2025):
+
+```
+domain = base32(sha-256(lowercase(::))).iso6523-actorid-upis.
+```
+
+Production zone: `edelivery.tech.ec.europa.eu`
+Test zone: `acc.edelivery.tech.ec.europa.eu`
+
+DNS NAPTR record returns the SMP base URL.
+
+Example for DIGG (`0007:2021006883`):
+
+```
+sha256("iso6523-actorid-upis::0007:2021006883") = ...
+base32(hash) = b-eepvcndgxw5tjr...
+NAPTR query: b-eepvcndgxw5tjr....iso6523-actorid-upis.edelivery.tech.ec.europa.eu
+```
+
+## SMP, Service Metadata Publisher
+
+The SMP is queried per **Peppol SMP specification v1.3.0 (February 2025)** for `ServiceGroup` (lists of supported document types) and `SignedServiceMetadata` (specific endpoint metadata, signed XML-DSIG). Endpoints expose:
+
+- `GET /`, ServiceGroup (list of document types).
+- `GET //services/`, SignedServiceMetadata (endpoint URL, AP certificate, transport profile, validity period).
+
+Transport profile is now **`peppol-transport-as4-v2_0`** for production (replaced the v1 profile in 2020).
+
+A given participant can be registered with **only one SMP at a time**. Migrating between APs requires the new AP to register the participant in its SMP and the old AP to deregister.
+
+## AS4 transport
+
+**Peppol AS4 Profile v2.0.x** is a profile of CEF eDelivery AS4 v1.14, which is itself a profile of OASIS ebMS3.
+
+Wire characteristics:
+- HTTPS, TLS 1.2+ (TLS 1.3 supported).
+- MIME multipart with single encrypted payload.
+- WS-Security message-level signing (RSA-SHA256) using the sender's AP certificate.
+- Encryption (AES-128-GCM or AES-256-GCM) using the recipient AP's certificate fetched from the SMP.
+- Single payload per AS4 message wrapping the **SBDH (Standard Business Document Header) v1.2** / **Peppol Business Message Envelope 2.0** which itself wraps the UBL document.
+
+**SBDH C1 country code mandatory since January 2024.** Oxalis 6.2.0+, Helger phase4 latest, and other compliant stacks enforce this. The SBDH carries `Sender`, `Receiver`, `DocumentIdentification` (standard, type version, instance ID), `BusinessScope` (process ID, document type ID, **C1 country code**).
+
+**From 1 February 2026**, SMP servers must run HTTPS on port 443 under the Peppol Policy for Transport Security.
+
+Authoritative spec: https://docs.peppol.eu/edelivery/as4/specification/
+
+## PKI, G2 to G3 migration
+
+The Peppol PKI migrated from **G2 (issued by IHC) to G3 (DigiCert One Trust Lifecycle)** during H2 2025. **G3-only after end-2025**, any test/production cert issued from 2026 onwards is G3.
+
+Two certificate types per Access Point:
+- **AP cert**, used for AS4 message signing and encryption.
+- **SMP cert**, used to sign `SignedServiceMetadata` responses.
+
+Cert validity is typically 1–2 years. Renewal is automated via DigiCert's portal; trust store updates flow via OpenPeppol member announcements.
+
+Trust store libraries (Helger `peppol-commons`, Oxalis) ship the bundled Peppol root and intermediate certs; update at least quarterly to track CA rotation.
+
+Issuance and enrolment process: https://openpeppol.atlassian.net/wiki/spaces/OPMA/pages/4439080961/Peppol+PKI+2025+-+Issuing+and+Enrolment+Process
+
+## Identifier schemes (ICD / EAS codes)
+
+Used as `schemeID` on `cbc:EndpointID`, `cac:PartyIdentification/cbc:ID`, etc.
+
+| Code | Authority | Use |
+|---|---|---|
+| **0007** | Bolagsverket organisationsnummer | Swedish primary |
+| **0088** | GS1 GLN | Swedish large orgs; recommended for sole proprietors (GDPR) |
+| **0192** | Norwegian Enhetsregisteret | Replaces deprecated `9908` |
+| **0184** | Danish CVR | Danish primary |
+| **0037** | Finnish LY-tunnus | Finnish primary |
+| **0208** | Belgian KBO/BCE | Belgian primary |
+| **0204** | German Leitweg-ID | German B2G mandatory |
+| **9930** | German VAT-ID | German B2B |
+| **0009** | French SIRET | French primary |
+| **0211** | Italian CodiceIPA | Italian B2G |
+| **0213** | Italian CodiceFiscale | Italian B2C |
+| **0096** | Dutch OIN | Dutch government |
+
+Authoritative live list: https://docs.peppol.eu/edelivery/codelists/ and https://docs.peppol.eu/poacc/billing/3.0/codelist/eas/.
+
+GitHub: https://github.com/OpenPEPPOL/peppol-bis-invoice-3/blob/master/structure/codelist/eas.xml
+
+## Becoming a Peppol Access Point, the operational path
+
+### OpenPeppol membership fees (effective 1 July 2025 for new members)
+
+For a small Swedish fintech (S1 size, 1–10 employees):
+
+| Path | Sign-up | Annual | Certification | Year-1 total |
+|---|---|---|---|---|
+| **AP + SMP S1** | €1,800 | €2,750 | €2,500 | **≈ €7,050** |
+| **AP-only S1+S2** | €1,050 | €1,850 | €1,500 | **≈ €4,400** |
+| **End User S1+S2** | €650 | €1,250 | n/a | **≈ €1,900** |
+
+Add infrastructure cost: 24/7 redundant AS4 hosting (€3–10k/yr), monitoring/on-call (€5–20k fully loaded), DigiCert G3 certs (bundled into OpenPeppol annual). DIGG charges no additional Peppol-Authority fee for Swedish service providers but requires signing the **Peppol Service Provider Agreement**.
+
+**Realistic minimum to operate an own AP: €20–40k/year direct cost plus 0.5–1 FTE engineering and 3–6 months upfront build.** Twice-yearly spec updates with a 7-day implementation window and mandatory monthly volume reporting are non-trivial recurring costs.
+
+### Onboarding steps
+
+1. Submit candidate application to `membership@peppol.eu`.
+2. Sign the **Peppol Member Agreement** with OpenPeppol AISBL.
+3. Sign the **Peppol Service Provider Agreement** (formerly Transport Infrastructure Agreement, TIA) with **DIGG** as Sweden's Peppol Authority.
+4. Implement AS4 + SMP lookup + SBDH handling. Deploy in test environment.
+5. Request DigiCert One G3 test certificate.
+6. Pass the **Peppol Testbed conformance suite**, refactored 2025 with country-specific payload tests. https://peppol.org/tools-support/testbed/
+7. Pay the Certification Fee.
+8. Production certificate issued.
+9. Register SMP in production SML via DIGG.
+10. Commit to monthly volume reporting.
+
+**Total elapsed time: 3–6 months.**
+
+### Open-source AS4 / SMP stacks
+
+- **Oxalis-NG** (https://github.com/OxalisCommunity/oxalis-ng), replaces Oxalis 6.x which is end-of-life Dec 2025. Java, Apache 2.0.
+- **Oxalis-AS4 7.x** (https://github.com/OxalisCommunity/oxalis-as4).
+- **Helger phase4** (https://github.com/phax/phase4), Apache 2.0 AS4 client + server.
+- **Helger phoss-smp**, production-grade SMP server.
+- **Helger peppol-commons**, identifiers, codelists, SBDH, SMP/SML clients.
+- **Helger phive + phive-rules**, validation engine and pre-built rules.
+- **Helger ph-ubl, ph-cii, ph-sbdh**, JAXB models.
+- **phase4-peppol-standalone**, Spring Boot 3 reference implementation (template, not turn-key).
+
+Trust stores updated to G3-only late 2025. Verify version when integrating.
+
+## DIGG Peppol traffic statistics (Q4 2025)
+
+- October 2025: record **5,668,209 Peppol messages** to Sweden.
+- November 2025: 4,810,015.
+- December 2025: 5,190,513.
+- Volume growth Sept 2024 → Sept 2025: **+30%**.
+- **25,000+ Swedish Peppol receivers** registered.
+- DIGG public sector survey (March 2025): 82% of public sector inbound invoices are e-invoices, 50% of outbound (up from 24%), 85% of public sector orgs use Peppol fully/largely for inbound.
+- Bankföreningen reports 168.9M e-invoices to consumers in 2024.
+- Total Swedish e-invoice volume estimate: **~250M/year** combining bank rails, Peppol B2G/B2B, and residual non-Peppol flows.
+
+Live stats: https://www.digg.se/digitala-tjanster/peppol/statistik-fran-peppolnatverket-
+
+## Authoritative source list
+
+- Peppol AS4 spec: https://docs.peppol.eu/edelivery/as4/specification/
+- Peppol SMP spec: https://docs.peppol.eu/edelivery/smp/specification/
+- SMP/SML interplay (Helger): https://peppol.helger.com/public/menuitem-docs-smp-sml-interplay
+- Setup AP guide: https://peppol.helger.com/public/menuitem-docs-setup-ap
+- Setup phoss SMP: https://peppol.helger.com/public/menuitem-docs-setup-smp-ph
+- Peppol Testbed: https://peppol.org/tools-support/testbed/
+- OpenPeppol membership: https://peppol.eu/who-is-who/openpeppol-membership/
+- DIGG how Peppol works: https://www.digg.se/digitala-tjanster/peppol/sa-fungerar-peppol-
+- Identifier policy: https://docs.peppol.eu/edelivery/codelists/
\ No newline at end of file
diff --git a/.claude/skills/swedish-e-invoicing/references/swedish-cius-and-specifics.md b/.claude/skills/swedish-e-invoicing/references/swedish-cius-and-specifics.md
new file mode 100644
index 00000000..9dbc0318
--- /dev/null
+++ b/.claude/skills/swedish-e-invoicing/references/swedish-cius-and-specifics.md
@@ -0,0 +1,315 @@
+# Sweden CIUS Rules and Accounting Integration
+
+This reference covers everything that is **specifically Swedish** in a Peppol BIS Billing 3 invoice: identifier formats, the SE-R-* validation rules, VAT rate handling, payment encoding for Bankgiro/Plusgiro/OCR, ROT/RUT and grön teknik handling, BAS-kontoplan postings, faktureringsmetoden vs kontantmetoden, and per-buyer BT-10 BuyerReference formats.
+
+## Swedish identifier formats
+
+### EndpointID (BT-34)
+
+```xml
+5567321000
+```
+
+- **Swedish orgnr** → `schemeID="0007"`, **10 digits, no dash**. Example: `5567321000` (not `556732-1000`).
+- **GLN** → `schemeID="0088"`, 13 digits. Used by larger organisations and DIGG-recommended for sole proprietors to avoid exposing personnummer.
+- **Sole proprietor with personnummer** → `schemeID="0007"` with the personnummer as a 10-digit orgnr (since personnummer IS the firma's orgnr). **GDPR concern**: routing metadata is visible across the Peppol network. DIGG recommends switching to GLN.
+
+### VAT identifier
+
+`cac:PartyTaxScheme/cbc:CompanyID` for a Swedish entity:
+
+```xml
+
+ SE556732100001
+ VAT
+
+```
+
+Format: **`SE` + 10 digits (orgnr) + `01`** (the trailing `01` is the legal sequence number, almost always `01`). The country prefix is mandatory under **BR-CO-9**.
+
+### Legal entity registration
+
+```xml
+
+ Arcim Technology AB
+ 5567321000
+ Godkänd för F-skatt
+
+```
+
+## SE-R-*, the Sweden CIUS rules
+
+### SE-R-005 (FATAL), F-skatt declaration
+
+If a Swedish supplier issues an invoice with VAT category `S`, **the literal string "Godkänd för F-skatt" must appear somewhere in the invoice**. Standard placements:
+
+- `cac:PartyLegalEntity/cbc:CompanyLegalForm` (preferred)
+- A document-level `cbc:Note`
+- An invoice-line `cbc:Note`
+
+This is the **single most common reason public sector authorities reject Swedish invoices**. Hard-code the string into the UBL template; do not derive it from a database flag (the F-skatt status of an active Swedish AB is universal).
+
+### SE-R-006, Swedish VAT rate restriction
+
+If supplier VAT country is `SE` and category is `S`, the rate must be **6, 12, or 25**. Any other rate must use category `E` (exempt) with an exemption reason, typically used for the rare zero-rate cases that are technically exempt rather than zero-rated.
+
+### SE-R-008 / SE-R-009, Bankgiro
+
+Bankgiro account numbers must be **7–8 numeric digits**.
+
+### SE-R-010, Plusgiro
+
+Plusgiro account numbers must be **2–8 characters**.
+
+### SE-R-011, Swedish payment methods
+
+PaymentMeansCode `30` (Credit transfer) is mandatory for both Bankgiro and Plusgiro. **Legacy codes 56 and 50 are explicitly forbidden.** The discriminator between Bankgiro and Plusgiro is `cac:FinancialInstitutionBranch/cbc:ID`:
+
+- `SE:BANKGIRO` for Bankgiro
+- `SE:PLUSGIRO` for Plusgiro
+
+### SE-R-013, Luhn validity on orgnr
+
+Swedish organisationsnummer must pass the modulus-10 (Luhn) check. Implementation note: the check digit is computed over the first 9 digits.
+
+## Swedish payment encoding (full example)
+
+Bankgiro payment with OCR reference:
+
+```xml
+
+ 30
+ 1234567890123
+
+ 5555-1234
+ Arcim Technology AB
+
+ SE:BANKGIRO
+
+
+
+```
+
+Plusgiro:
+
+```xml
+
+ 30
+ 1234567890123
+
+ 123456-7
+
+ SE:PLUSGIRO
+
+
+
+```
+
+For non-Swedish EU payments use code `58` (SEPA credit transfer) with country-checked IBAN in `cbc:ID`.
+
+## OCR references
+
+Swedish OCR is numeric, **2–25 digits, last digit modulus-10 (Luhn) check**. Optional length digit at position n−1 encodes total length.
+
+Four control levels at Bankgirot:
+- **OCR1**, soft (mjuk), Luhn only.
+- **OCR2**, hard (hård), Luhn + reference exists in BG receiver's reference register.
+- **OCR3**, fixed length via length digit.
+- **OCR4**, fixed length, up to 3 lengths allowed.
+
+Hård kontroll causes internet-banks to reject mismatched OCR, test thoroughly before going live. Encode in `cbc:PaymentID` (BT-83).
+
+## Bankgirot integration mechanics
+
+### Inbound payment file (kundreskontra)
+
+Bankgirot's daily inbound file uses fixed-format records with TK (transaction code):
+
+| TK | Meaning |
+|---|---|
+| 05 | Inbetalning |
+| 15 | Avdrag/return |
+| 25 | Inbetalning utan referens |
+| 27 / 28 / 29 | Bg/Pg variations |
+| 70 | Justering |
+
+The OCR (BT-83 / `cbc:PaymentID`) is the match key driving automatic invoice closure in 1510 Kundfordringar.
+
+### Outbound LB-rutin (leverantörsbetalningar)
+
+Outbound payment file uses TK 11/14/16/17/25/26/27/29/49 records, supports Girering, Kontoinsättning (clearing+kontonr), Kontantutbetalning and Avräkning av kreditfaktura. Signed and submitted via the company's bank (BgCom / BankgiroLink). The återredovisningsfil drives AP closure in 2440 Leverantörsskulder.
+
+**P27 was abandoned in 2023.** Banks have introduced bank-specific ISO 20022 PAIN.001/.002 flows. **Plan for LB-rutin and ISO 20022 to coexist for the foreseeable future.**
+
+## VAT (moms) rates and category encoding
+
+Swedish rates: **25% standard, 12% (food, hotel, restaurant), 6% (books, transport, culture, sport), 0%**.
+
+Standard 25% line example:
+
+```xml
+
+ S
+ 25
+ VAT
+
+```
+
+Reverse charge for byggtjänster (omvänd skattskyldighet bygg, ML 2 kap. 1 § p. 4) within Sweden, uses `AE`:
+
+```xml
+
+ AE
+ 0
+ VAT
+
+```
+
+Buyer's bookkeeping must post 2647 Ingående moms omvänd skattskyldighet (DR) and 2614 Utgående moms omvänd skattskyldighet (CR) when receiving such an invoice.
+
+Intra-EU service to a B2B EU customer, uses `K` (sometimes `AE` depending on supply rule):
+
+```xml
+
+ K
+ 0
+ VAT
+
+```
+
+With `VATEX-EU-IC` exemption reason in the summary `TaxCategory`.
+
+## BAS-kontoplan postings
+
+The de-facto chart is **BAS-kontoplanen** (https://www.bas.se), updated yearly. Key accounts for e-invoice flows:
+
+### Customer-side (kundfakturor)
+
+- **1510** Kundfordringar (AR control, primary)
+- **1513** Kundfordringar i delbetalning (used for ROT/RUT split)
+- **1515** Osäkra kundfordringar
+- **1518** Ej reskontraförda kundfordringar
+- **1519** Värdereglering kundfordringar
+- **3001/3002/3003/3004** Försäljning by VAT rate (25/12/6/0%)
+- **3308** Försäljning tjänst utanför EU
+- **3573** Försäljning tjänst EU (för uppgift i periodisk sammanställning)
+
+### Supplier-side (leverantörsfakturor)
+
+- **2440** Leverantörsskulder (AP control, primary)
+- **2445** Tvistiga leverantörsskulder
+- **2448** Ej reskontraförda leverantörsskulder
+- **4010** Inköp varor
+- **4515** Inköp tjänster
+- **4xxx** General cost-of-goods accounts
+
+### VAT control
+
+- **2611** Utgående moms 25%
+- **2621** Utgående moms 12%
+- **2631** Utgående moms 6%
+- **2614** Utgående moms omvänd skattskyldighet
+- **2615** Utgående moms 25% EU varuinköp
+- **2641** Ingående moms (inland)
+- **2645** Ingående moms utländska leverantörer
+- **2647** Ingående moms omvänd skattskyldighet (e.g. byggmoms)
+- **2650** Redovisningskonto för moms (clearing to Skatteverket)
+
+### Cash and bank
+
+- **1910** Kassa
+- **1920** Plusgiro
+- **1930** Företagskonto / Bank
+
+## Standard postings
+
+**Outbound invoice 1,000 SEK net + 25% VAT to Swedish customer (faktureringsmetoden):**
+
+```
+DR 1510 Kundfordringar 1 250
+ CR 3001 Försäljning 25% 1 000
+ CR 2611 Utgående moms 25% 250
+```
+
+**Inbound supplier invoice 1,000 SEK net + 25% VAT (faktureringsmetoden):**
+
+```
+DR 4010 Inköp 1 000
+DR 2641 Ingående moms 25% 250
+ CR 2440 Leverantörsskulder 1 250
+```
+
+**Inbound construction reverse-charge supplier invoice 1,000 SEK:**
+
+```
+DR 4xxx Inköp byggtjänst 1 000
+DR 2647 Ingående moms omvänd 250 (reclaimable)
+ CR 2440 Leverantörsskulder 1 000
+ CR 2614 Utgående moms omvänd 250 (collected)
+```
+
+Net effect on moms is zero, but both legs must be reported in momsdeklarationen.
+
+## Faktureringsmetoden vs kontantmetoden
+
+- **Faktureringsmetoden**, mandatory if turnover > **SEK 3 million**, default for AB. Books invoices on issuance against 1510/2440. Moms recognised on invoice date.
+- **Kontantmetoden**, books only on payment, against 1930/1910. Year-end conversion mandatory: any outstanding kund-/leverantörsfaktura must be booked over to 1510/2440 and the underlying intäkt/kostnad recognised, then reversed on 1 Jan.
+
+The bookkeeping engine must carry a `bookkeeping_method` flag driving posting timing and a year-end converter routine.
+
+## ROT/RUT and grön teknik
+
+**Peppol BIS Billing 3 has no standardised ROT/RUT extension.** Production practice in Swedish ERPs:
+
+1. **On the invoice**: show a reduced "Att betala" amount (after Skatteverket's portion).
+2. **Surface the deduction** as an `cac:AllowanceCharge` with informative reason (no standardised reason code, use `cbc:AllowanceChargeReason` text).
+3. **Persist housework metadata** locally against Skatteverket's typkoder:
+ - **ROT-bygg**: Bygg, El, Glas/Plåt, Mark/Dränering, Murning, Målning/Tapetsering, VVS.
+ - **RUT**: Städning, Trädgård, Barnpassning, Övriga (incl. flytt, IT-arbete, snöskottning).
+ - **Grön teknik**: värmepump-schablon, solceller, lagring, laddpunkt.
+4. **After payment**, generate Skatteverket's separate "Begäran om utbetalning" XML (`HUSXML`) and upload via Skatteverket's e-tjänst.
+
+Bookkeeping splits the customer receivable into customer-paid and Skatteverket-receivable portions:
+
+```
+DR 1510 Kundfordringar (kund) 500 (kund's net to pay)
+DR 1684 Skatteverket ROT-fordran 500 (or 1513 / 1689)
+ CR 3001 Försäljning 25% 1 000
+ CR 2611 Utgående moms 25% ...
+```
+
+The 1684/1513/1689 receivable is closed when Skatteverket disburses to the company's bank.
+
+## BT-10 BuyerReference per-buyer formats
+
+Each Swedish public sector buyer specifies its own BT-10 / BuyerReference format. Examples:
+
+| Buyer | Format |
+|---|---|
+| Skatteverket | 4-letter code |
+| Svenska Kraftnät | 3 digits + 3 letters |
+| Försäkringskassan | 5–10 digits starting with `4` |
+| Many universities | cost-centre + name |
+
+**Maintain a per-buyer-Peppol-ID regex map** and validate at invoice compose time. This prevents 30-day public-sector payment delays. Scrape SFTI / docplayer reference and update quarterly.
+
+## Multi-currency (Swedish supplier invoicing in EUR)
+
+Swedish supplier issuing in EUR to an EU customer; book the SEK equivalent for VAT.
+
+```xml
+EUR
+SEK
+```
+
+Bookkeeping uses the **monthly average ECB rate** for the previous month (Skatteverket-accepted), or the day's spot rate if the contract specifies. Both rate sources are valid; document the policy.
+
+## Authoritative source list
+
+- BAS-kontoplan: https://www.bas.se
+- SFTI Peppol BIS Billing 3: https://sfti.se/sfti/standarder/peppolbisehandel/peppolbisbilling3.49021.html
+- Swedish payment methods in BIS 3: https://support.inexchange.com/hc/en-us/articles/360001888178-Swedish-Payment-Methods-in-PEPPOL-BIS-3
+- DIGG Peppol-ID instructions: https://www.digg.se/digitala-tjanster/peppol/instruktion-for-val-av-peppol-id-
+- SE-R-005: https://docs.peppol.eu/poacc/billing/3.0/rules/ubl-peppol/SE-R-005/
+- SE-R-011: https://docs.peppol.eu/poacc/billing/3.0/rules/ubl-peppol/SE-R-011/
+- Skatteverket ROT/RUT XML: https://www.skatteverket.se/foretag/rotochrutarbete (HUSXML schema)
\ No newline at end of file
diff --git a/app/api/bookkeeping/journal-entries/__tests__/route.test.ts b/app/api/bookkeeping/journal-entries/__tests__/route.test.ts
index fc47189d..b8636361 100644
--- a/app/api/bookkeeping/journal-entries/__tests__/route.test.ts
+++ b/app/api/bookkeeping/journal-entries/__tests__/route.test.ts
@@ -123,6 +123,23 @@ describe('GET /api/bookkeeping/journal-entries', () => {
expect(body.count).toBe(2)
})
+ it('forwards explicit ?status=cancelled to the RPC', async () => {
+ enqueue({ data: [], error: null })
+
+ const request = createMockRequest('/api/bookkeeping/journal-entries', {
+ searchParams: { period_id: 'period-1', status: 'cancelled' },
+ })
+ await GET(request)
+
+ // The RPC itself hides cancelled entries unless p_status='cancelled' is
+ // passed explicitly (see migration 20260428153500). The behavior of the
+ // hide-by-default logic lives in SQL and is covered by pg-real tests.
+ expect(mockSupabase.rpc).toHaveBeenCalledWith(
+ 'list_fiscal_period_entries_with_related',
+ expect.objectContaining({ p_status: 'cancelled' })
+ )
+ })
+
it('returns 500 on database error', async () => {
enqueue({ data: null, error: { message: 'DB error' } })
diff --git a/app/api/bookkeeping/journal-entries/route.ts b/app/api/bookkeeping/journal-entries/route.ts
index c1c38ce0..3352c427 100644
--- a/app/api/bookkeeping/journal-entries/route.ts
+++ b/app/api/bookkeeping/journal-entries/route.ts
@@ -84,6 +84,8 @@ export async function GET(request: Request) {
if (status) {
query = query.eq('status', status)
+ } else {
+ query = query.neq('status', 'cancelled')
}
if (dateFrom) {
diff --git a/components/reports/SkatteverketPanel.tsx b/components/reports/SkatteverketPanel.tsx
index eb945f77..03f8aff5 100644
--- a/components/reports/SkatteverketPanel.tsx
+++ b/components/reports/SkatteverketPanel.tsx
@@ -8,7 +8,9 @@ import { Badge } from '@/components/ui/badge'
import {
AlertCircle,
CheckCircle2,
+ Download,
ExternalLink,
+ Gavel,
Link2,
Link2Off,
Loader2,
@@ -17,6 +19,7 @@ import {
Unlock,
Send,
ShieldAlert,
+ Trash2,
} from 'lucide-react'
import type { VatPeriodType } from '@/types'
import { formatRedovisare, formatRedovisningsperiod } from '@/lib/skatteverket/format'
@@ -29,10 +32,12 @@ interface SkatteverketStatus {
expiresAt?: string
}
+// Shape per Skatteverket Momsdeklaration v1.0.24 RAML
+// (kontrollResultat.resultat[].{kod, status, beskrivning})
interface KontrollResult {
- id: string
- typ: 'ERROR' | 'WARNING'
- text: string
+ kod: string
+ status: 'ERROR' | 'WARNING'
+ beskrivning: string
}
interface SkatteverketPanelProps {
@@ -141,12 +146,12 @@ function SkatteverketPanelInner({ periodType, year, period, hasData }: Skattever
if (result.error) {
setError(result.error)
} else {
- const controls = result.data?.kontrollresultat?.kontroller || []
+ const controls: KontrollResult[] = result.data?.kontrollResultat?.resultat || []
setKontroller(controls)
if (controls.length === 0) {
setSuccess('Valideringen godkänd — inga fel eller varningar')
} else {
- const errors = controls.filter((k: KontrollResult) => k.typ === 'ERROR')
+ const errors = controls.filter(k => k.status === 'ERROR')
if (errors.length > 0) {
setError(`${errors.length} valideringsfel hittades`)
} else {
@@ -174,9 +179,9 @@ function SkatteverketPanelInner({ periodType, year, period, hasData }: Skattever
if (result.error) {
setError(result.error)
} else {
- const controls = result.data?.kontrollresultat?.kontroller || []
+ const controls: KontrollResult[] = result.data?.kontrollResultat?.resultat || []
setKontroller(controls)
- const errors = controls.filter((k: KontrollResult) => k.typ === 'ERROR')
+ const errors = controls.filter(k => k.status === 'ERROR')
if (errors.length === 0) {
setSuccess('Utkast sparat i Eget utrymme hos Skatteverket')
} else {
@@ -203,8 +208,8 @@ function SkatteverketPanelInner({ periodType, year, period, hasData }: Skattever
const result = await res.json()
if (result.error) {
setError(result.error)
- } else if (result.data?.signeringslank) {
- setSigneringslank(result.data.signeringslank)
+ } else if (result.data?.signeringsLank) {
+ setSigneringslank(result.data.signeringsLank)
setSuccess('Utkastet är låst. Öppna signeringslänken för att signera med BankID.')
}
} catch {
@@ -263,6 +268,84 @@ function SkatteverketPanelInner({ periodType, year, period, hasData }: Skattever
}
}
+ const handleDeleteDraft = async () => {
+ setActionLoading('delete')
+ setError(null)
+ try {
+ const res = await fetch(
+ `/api/extensions/ext/skatteverket/declaration/draft?redovisare=${encodeURIComponent(
+ await getRedovisare()
+ )}&redovisningsperiod=${getRedovisningsperiod()}`,
+ { method: 'DELETE' }
+ )
+ if (res.status === 204 || res.ok) {
+ setKontroller([])
+ setSigneringslank(null)
+ setSuccess('Utkastet har raderats från Eget utrymme')
+ } else {
+ const result = await res.json().catch(() => ({}))
+ setError(result.error || `Kunde inte radera utkast (${res.status})`)
+ }
+ } catch {
+ setError('Kunde inte radera utkast')
+ } finally {
+ setActionLoading(null)
+ }
+ }
+
+ const handleFetchDraft = async () => {
+ setActionLoading('fetchDraft')
+ setError(null)
+ try {
+ const res = await fetch(
+ `/api/extensions/ext/skatteverket/declaration/draft?redovisare=${encodeURIComponent(
+ await getRedovisare()
+ )}&redovisningsperiod=${getRedovisningsperiod()}`
+ )
+ const result = await res.json()
+ if (result.error) {
+ setError(result.error)
+ } else if (!result.data) {
+ setSuccess('Inget sparat utkast hittades för perioden')
+ } else {
+ const locked = result.data?.locked ? ' (låst)' : ''
+ const summa = result.data?.momsuppgift?.summaMoms
+ const summaLabel = summa !== undefined ? `, summaMoms = ${formatAmount(summa)}` : ''
+ setSuccess(`Sparat utkast hittades${locked}${summaLabel}`)
+ }
+ } catch {
+ setError('Kunde inte hämta utkast')
+ } finally {
+ setActionLoading(null)
+ }
+ }
+
+ const handleFetchDecided = async () => {
+ setActionLoading('fetchDecided')
+ setError(null)
+ try {
+ const res = await fetch(
+ `/api/extensions/ext/skatteverket/declaration/decided?redovisare=${encodeURIComponent(
+ await getRedovisare()
+ )}&redovisningsperiod=${getRedovisningsperiod()}`
+ )
+ const result = await res.json()
+ if (result.error) {
+ setError(result.error)
+ } else if (!result.data) {
+ setSuccess('Inget beslut hittades för perioden')
+ } else {
+ const tid = result.data?.beslutadTidpunkt
+ const tidLabel = tid ? ` (beslutad ${new Date(tid).toLocaleDateString('sv-SE')})` : ''
+ setSuccess(`Beslut hittades${tidLabel}`)
+ }
+ } catch {
+ setError('Kunde inte hämta beslutade uppgifter')
+ } finally {
+ setActionLoading(null)
+ }
+ }
+
// Helper to get redovisare from settings
const getRedovisare = async (): Promise => {
const res = await fetch('/api/settings')
@@ -316,8 +399,8 @@ function SkatteverketPanelInner({ periodType, year, period, hasData }: Skattever
}
// Connected — show actions
- const hasErrors = kontroller.some(k => k.typ === 'ERROR')
- const hasWarnings = kontroller.some(k => k.typ === 'WARNING')
+ const hasErrors = kontroller.some(k => k.status === 'ERROR')
+ const hasWarnings = kontroller.some(k => k.status === 'WARNING')
return (
@@ -364,21 +447,21 @@ function SkatteverketPanelInner({ periodType, year, period, hasData }: Skattever
+
+ {/* Recovery / cleanup buttons. Always visible when connected so
+ the user can back out of a locked or stale draft state without
+ depending on local UI state surviving a reload. SKV returns
+ 404/409 if the action isn't applicable; we surface that as an
+ error message rather than hiding the button. */}
+