diff options
Diffstat (limited to 'docs/COMPLIANCE.md')
| -rw-r--r-- | docs/COMPLIANCE.md | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/docs/COMPLIANCE.md b/docs/COMPLIANCE.md new file mode 100644 index 0000000..a152cd4 --- /dev/null +++ b/docs/COMPLIANCE.md @@ -0,0 +1,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. |
