aboutsummaryrefslogtreecommitdiff
path: root/docs/COMPLIANCE.md
blob: a152cd473de5f3baeb06c7364e0d1615acdec7e3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# bokf compliance notes

Status: Draft 0.1 · 2026-09-17 · License: GPL-3.0-or-later

This document maps Swedish bookkeeping requirements to concrete `bokf`
features, and states plainly what the software does **not** do. It is a design
document, not legal advice. Statutory references are indicative — verify the
current wording, and engage a redovisningskonsult or revisor before relying on
any of it.

The short version: no Swedish authority certifies bookkeeping software.
Compliance is always the responsibility of the bokföringsskyldige. `bokf`'s goal
is to make the formal requirements hard to violate by construction: append-only
data, enforced number series, verifiable history and locked periods.

## 1. Framework

| Source | What it governs |
|---|---|
| Bokföringslagen (1999:1078), BFL | Bookkeeping duty, löpande bokföring, verifikationer, bevarande |
| BFNAR 2013:2, vägledning om räkenskapsinformation | Systemdokumentation, behandlingshistorik, rättelser, säkerhet |
| Årsredovisningslagen (1995:1554), ÅRL | Årsredovisning, Bolagsverket filing |
| BFNAR 2016:10 (K2), BFNAR 2012:1 (K3) | Accounting frameworks for AB |
| Mervärdesskattelagen (2023:200), ML | Moms reporting |
| SIE 4 | De facto exchange standard between systems, banks, accountants, auditors |
| BAS-kontoplanen (FAR) | Standard chart of accounts; separately attributed seed data |
| GDPR | Personal data in the ledger and in user management |

## 2. Requirement → feature map

| Requirement | Where in bokf | Status |
|---|---|---|
| **Löpande bokföring** (BFL 4 kap) — entries made continuously, in Swedish kronor, in chronological order | Every voucher has a date within its fiscal year; listings are ordered by date, series, number; server rejects out-of-range dates | MVP |
| **Verifikationer** (BFL 5 kap) — every entry has a dated verification with underlag, amount, counterpart, and identifies the counterparty | `voucher.post` requires description, ≥ 2 balanced rows, account references, actor identity; underlag via immutable `attachments` linked to the voucher | MVP |
| **Obruten nummerserie** per räkenskapsår | `sequences` incremented in the same transaction as the insert; a failed post consumes nothing, a committed post skips nothing; `UNIQUE(org, year, series, number)` | MVP |
| **Oföränderlighet** — a verifikation may not be altered after the fact | `BEFORE UPDATE/DELETE` triggers abort on vouchers, rows, attachments and audit. No application command can change ledger rows | MVP |
| **Rättelser** — errors corrected by a new verifikation that references the old (ändringsverifikat), never by editing | `voucher.correct` mirrors and posts a new voucher carrying `corrects_voucher_id`; original remains visible with both linked in reports | MVP |
| **Behandlingshistorik** (BFNAR 2013:2) — who did what, when, with what result | `audit_log`, append-only, SHA-256 chained, one entry per mutation with actor user **and** token; `audit.verify` recomputes the chain | MVP |
| **Systemdokumentation** (BFNAR 2013:2) | `docs/` (this file, `PROTOCOL.md`, `SCHEMA.md`), `meta.schema_version`, runtime `describe`; the operator must keep it current for their installation | MVP, operator duty |
| **Bevarande i 7 år** (BFL 7 kap) | Append-only storage; no delete commands for ledger data; `archive`/disable instead of delete; `backup.snapshot` + restic pattern produces dated, restorable archives | MVP, operator duty |
| **Tillgänglighet och läsbarhet** | JSON reports, SIE 4 export in CP437, SIE import; the archive is readable by any tool that reads SQLite or SIE | MVP |
| **Huvudbok, saldon** (god redovisningssed) | `report.general_ledger`, `report.trial_balance`, `report.balance_sheet`, `report.income_statement` | MVP |
| **Moms** (ML 2023:200) | `report.vat` computes the boxes from `report_rules`; declaration is filed with Skatteverket by the operator | MVP in-system; eSKD file generation roadmap |
| **SIE 4** | `sie.export` (PC8/CP437) and `sie.import` (migration from Fortnox/Visma/BL) | MVP |
| **Årsredovisning / INK2 / SRU** (ÅRL, K2) | Reports supply the figures; document generation and SRU files are roadmap | Roadmap |
| **AGI, arbetsgivaravgifter, löner** | Not present | Roadmap |
| **Fakturering, kund- och leverantörsreskontra** | Not present | Roadmap |
| **Kontrolluppgifter, periodiska sammanställningar** | Not present | Roadmap / manual |
| **GDPR** — lawful basis for ledger personal data, retention overrides erasure | Role-based access, revocable tokens, audit trail, local hosting; see §5 | MVP in-system, operator duty |

## 3. How invariants are enforced

The interesting detail is that compliance here is not a feature that can be
switched off, or bypassed by a clever client:

1. **The server owns the invariants.** Clients — including agents — cannot
   construct a voucher that skips a number, exceeds a lock, or references
   another org's account.
2. **The database enforces tenancy.** Composite keys make cross-org references
   impossible at the storage layer (`SCHEMA.md` §1, §4–7).
3. **The database enforces immutability.** Triggers abort updates and deletes
   on ledger and audit tables. This also holds for manual `sqlite3` access as
   root.
4. **History is verifiable.** Voucher and audit chains are recomputable by
   `audit.verify`; tampering is detectable, not just forbidden.
5. **Locks are explicit.** `period.lock` is owner-only and every unlock is
   logged with a reason. `fiscal_year.close` is irreversible from the API.

## 4. Verifikationer and the correction flow

- A voucher = verifikation: unique number in an unbroken series, date,
  description, rows, creator, timestamp, hash, linked underlag.
- Corrections per BFNAR 2013:2: post an ändringsverifikat with
  `voucher.correct`, referencing the original. Both remain in the ledger and in
  every report; the link is machine-readable.
- Deleting or hiding a posted voucher is not possible; there is no command for
  it and no SQL path to it under normal operation.
- Underlag (receipts, invoices) live in the same database as immutable blobs,
  linked to exactly the vouchers they support. Missing-underlag is a
  first-class query (`attachment.list {unlinked:...}` and per-voucher coverage).

## 5. Data location, backups and the 7-year archive

- Plan to host within the EES and keep the data available for inspection.
  BFL's rules on where räkenskapsinformation may be kept and how it must be
  presentable are precise — check the current 7 kap. wording for your case.
  `bokf` makes no transfers anywhere; there is no telemetry and no cloud
  dependency.
- **Never back up live SQLite files with a file-copy tool.** Use
  `backup.snapshot` (`VACUUM INTO`), which produces a consistent single file
  with no downtime, then let restic pick that up. Exclude the live
  `*.db`/`-wal`/`-shm` from restic.
- Test restores on a schedule; a backup that has never been restored is not an
  archive. The restore procedure is also the retrieval path for inspections.
- 7 years = seven years after the calendar year in which the fiscal year
  ended. Restic retention is not a legal retention policy by itself: keep at
  least annual snapshots for the full period and store them somewhere you can
  still read in a decade.

## 6. Roles, audit and access

| Actor | Typical holder | Sees |
|---|---|---|
| `owner` | You | Everything, including unlocks, closing and member management |
| `bookkeeper` | Accounting help | Books and reports, posts and corrects, no irreversible ops |
| `viewer` | Revisor, auditor, board member | Read-only, including audit history |
| token | Agent or integration | Narrowed scope, its own audit identity, revocable instantly |

Every mutation records the acting user **and** token, so machine-written
entries are attributable to the machine and to the human who authorized it.
Passwords and tokens never reach the audit log or the application log.

## 7. GDPR notes

- Ledger personal data (customer/supplier names, employee data later) is
  processed under legal obligation (BFL), not consent; retention periods
  override erasure requests. A data subject request must be answered within
  those constraints, not by deleting bookkeeping.
- User accounts (name, username, password hash, token metadata) are kept to
  operate the service; disable instead of delete when history references them.
- Because everything is single-host, data subject access requests can be
  answered from reports and audit listings; there is no third party to notify.
- Keep the host physically and network secured: LUKS at rest, no public
  listener by default, tokens revocable, sessions short-lived.

## 8. What the operator still must do

The software does not file anything, sign anything, or know your business:

- File momsdeklaration, AGI, INK2 and other declarations with Skatteverket
  (upload files once the eSKD/SRU roadmap items land, or via the e-service).
- Prepare and sign the årsredovisning and file it with Bolagsverket; K2
  generation is roadmap, and the figures still need review.
- Keep a current systemdokumentation for the installation (hardware, OS,
  backup, access) — `docs/` is the starting point.
- Decide the moms period, fiscal year and accounting framework per org
  (`org.create` args) and keep them correct.
- Test restores; hold two independent backup copies.
- Have a redovisningskonsult or revisor review at least the first year.
- Remember that only humans can exercise judgement: VAT treatment, fringe
  benefits, cut-off, going concern.

## 9. Honest status

This is a draft specification. Nothing here has been audited, and the system
has no production history yet. Treat generated reports and declaration
figures as you would any new tool's output: review before filing. The
compliance value of `bokf` rests on the enforced invariants above, not on
approval by any authority — none exists.

## 10. Roadmap, in rough order

1. Ledger core + protocol + CLI + TUI (MVP).
2. SIE round-trip test suite and migration dry-run against files exported from
   Fortnox/Visma/BL.
3. eSKD file for momsdeklaration; AGI file for payroll.
4. K2 årsredovisning document generation + SRU files for INK2.
5. Invoicing and reskontra; bank import (CSV, then PSD2).
6. Peppol e-invoicing, if still relevant when it is due.