summaryrefslogtreecommitdiff
path: root/docs/COMPLIANCE.md
diff options
context:
space:
mode:
authorAnders Betts <anders.betts@gmail.com>2026-09-17 19:55:36 +0200
committerAnders Betts <anders.betts@gmail.com>2026-09-17 19:55:36 +0200
commit380195f7cd5e57acf2c1cf2bc41069e6b0b979ed (patch)
tree32a88fb22a7fbe8f1fd5c105156d1f928c93950d /docs/COMPLIANCE.md
downloadbokf-0.1.0.tar.gz
bokf-0.1.0.zip
Initial commit: daemon, clients, docs, Docker deploy pipelinev0.1.0
Diffstat (limited to 'docs/COMPLIANCE.md')
-rw-r--r--docs/COMPLIANCE.md159
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.