summaryrefslogtreecommitdiff
path: root/docs/STATE.md
blob: 56a23ed252f7619b01067013e10227e2226a0c36 (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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# bokf — project state

Settled decisions live in `docs/DECISIONS.md`; this file is the live snapshot.
Read with `AGENTS.md` (rules) and `docs/TUI-GUIDELINES.md` (UI conventions).

## Status

Working self-hosted bookkeeping system, not production-proven. Backend ledger
core is complete, as are invoicing, the payroll engine and the payroll TUI;
filing/year-end work remains. TUI is usable and exercised by `make test-pty`
(golden screen-text scenarios, now including the payroll run and the
lönebesked); `make test` covers the server/protocol/ledger, the TUI widget
unit tests and the docs consistency check.

## Resume here (2026-09-21)

- **Deployed**: `v0.1.59`, healthy on `nas` (Alpine runtime, static aarch64
  binaries cross-compiled on this machine — ~20 s, the host only assembles
  the image; image 33.7 MB, no `libssl3`). `v0.1.55` brought the payroll
  server waves (schema v11: employees, tax tables, lönebesked) and the
  payroll TUI; `v0.1.56` the **Bolaget** hub; `v0.1.57` the flat main menu
  without section headings, the **System** hub (Skattetabeller, Revision)
  and the client-side remembered attachment directory; `v0.1.58` loads the
  system CA bundle explicitly so the static binaries can verify TLS (the
  Skatteverket fetch, SMTP, static clients); `v0.1.59` fixes form saving on
  modern terminals (modifyOtherKeys level 2, Kitty keyboard protocol, and
  `^Enter/F9` in the hints). The live database migrated v9 → v11 on the
  v0.1.55 startup with the automatic pre-migration snapshot in
  `var/db/backup/`. `main` and the tags are pushed to `nas`.
- **Next tasks (payroll follow-ups)**: fold `payroll.settings_get/set` into
  `settings.get/set` (cmd_settings.c was busy during wave 1); settle the
  over-80k % rule (SKV 433 leaves it ambiguous — currently a clear
  `INVALID_ARGS`); move `invoice.send` to the shared `src/mail.c`. The TUI
  has no screen for the payroll account/rate settings yet (they are
  defaults and can stay server-side until the fold).
- **Done in the TUI wave**: `clients/screens_payroll.c` with Lönekörningar
  (list + Ctrl+N, run screen with F5 preview, Ctrl+Enter post after
  confirmation and the action rows Lönebesked, AGI-underlag, Betala skatt &
  avgifter), Anställda under Företag and the Skattetabeller
  fetch/import/status screen under System. A pty scenario posts a run and
  fetches its lönebesked, so the payslip PDF path is exercised end to end.
- **Menu (2026-09-21)**: the dashboard is one flat list without section
  headings: Verifikat, Underlag, Bankavstämning, Mallar, Fakturor,
  Lönekörningar, Rapporter, Bokslut, Bolaget, System, Ingående balans,
  Räkenskapsår, Logga ut. **Bolaget** is the master-data hub
  (Företagsuppgifter, Fakturauppgifter with Nästa fakturanummer,
  **Verifikationsserier**, E-post (SMTP), Styrelseledamöter and the
  registers Anställda, Kunder, Momsregler); **System** holds
  Skattetabeller and Revision. Inställningar is gone, and bilagornas mapp
  is no longer a setting: the file browser remembers the last pick
  directory in `tui.conf` and falls back to `$HOME`. `--screen settings`
  remains an alias for Bolaget.

## Open decisions

None open. Completed items that used to be listed here are archived in
`docs/DECISIONS.md`.

## Backlog (prioritized, from COMPLIANCE.md §10 and the audit)

1. ~~eSKD file generation~~ done: `report.vat_eskd`.
2. ~~Bokslut automation~~ done: `bokslut.post` + TUI Bokslut screen.
3. ~~K2 årsredovisning draft and SRU files~~ done: TUI draft + `sru.export`.
4. ~~`audit.verify` voucher chain~~ done (also attachments with `full:true`).
5. ~~`report.general_ledger` / `report.voucher_list`~~ done.
6. ~~`describe` argument schemas~~ done (`CMD_ARGS`).
7. ~~Pre-migration `VACUUM INTO` snapshot~~ done.
8. ~~Docker image + compose~~ done (no registry, no systemd unit).
9. Password change, user disable, TOTP.
10. ~~Bank import/reconciliation (CSV first)~~ phase 1 (SEB CSV + matching,
    schema v8) and phase 2 (Ctrl+N prefills the voucher and auto-matches it,
    `9b1021e`) done. Phase 3 (`bank_rule.*`) **dropped by the user
    2026-09-21**; PSD2 only if it ever hurts.
11a. Imported history years with source P&L closings: decided, no importer
    change (see DECISIONS.md).
11. ~~SIE import only into an empty fiscal year~~ chronological multi-year
    import works; each year must still target an empty fiscal year.
12. TUI polish: horizontal scrolling in long text fields, bracketed paste.
13. ~~Payroll TUI (wave 3)~~ done (`clients/screens_payroll.c`); the
    remaining payroll follow-ups are listed under "Resume here". No
    employee is registered yet in the real orgs.
14. Invoice follow-ups when needed: credit notes (`invoice.credit`), per-row
    account in the invoice form, kundreskontra view.
15. `make test-pty` speed if it ever exceeds ~60 s: parallelise the
    independent scenarios (each has its own rig) and add `--only` symmetry;
    measure first.
16. Test fixtures (`t_fresh_org()`) + one test file per domain
    (`tests/core_<domain>.c`) so `--only` stops cascading; pilot with one
    domain.

Original entries for the struck items are in `docs/DECISIONS.md`.

## Environment / how to run

- **Deployed**: `scripts/deploy.sh` (latest `v0.1.59`, healthy on nas).
  Live daemon `tls:bokf.makandra.eu:8788`, token
  `~/.config/bokf/migration-token` (scopes `read,write`; owner-only actions
  like closing years must be done by the human in the TUI). Git remote
  `origin` is `nas:/mnt/data/git-repos/bokf.git` (push `main` and tags).
  `sh scripts/install-hooks.sh` once per checkout points `core.hooksPath` at
  `.githooks/`, so every push runs `make gate` (clean `-Werror` build in
  `build-gate/`, the suite and ASan); it is installed here.
  `deploy/Dockerfile.cross` + `deploy/cross-build.sh` produce static aarch64
  `bokfd`/`bokfctl` in ~20 s when the host architecture differs; the image is
  assembled on the host from `.prebuilt` (see docs/DEPLOY.md).
- **Local test rig** (transient, `/tmp`): daemon
  `./build/bokfd --db /tmp/opencode/bokf-local/t.db --socket
  /tmp/opencode/bokf-local/sock`, org 1, login `admin`/`testpass123`.
  Drive the TUI over a pty with `scripts/tui-sandbox.sh -- ./build/bokftui
  --socket /tmp/opencode/bokf-local/sock --org 1 --fy 1 ...` plus a small
  driver that feeds keys and an ANSI renderer (recreate if gone; arrows are
  `ESC O B/A`, Tab `\t`, `^X` `\x18`, `^Enter` `ESC[27;5;13~`, F5
  `ESC[15~`). Never test against the live daemon.


- Demo: db `~/bokf-demo/bokfd.db`, socket `~/bokf-demo/bokfd.sock`,
  pid file `~/bokf-demo/bokfd.pid`; login `admin` / `demo1234`.
  Start TUI: `cd ~/work/bokf && BOKFD_SOCKET=$HOME/bokf-demo/bokfd.sock \
  BOKFD_USER=admin BOKFD_PASSWORD=demo1234 ./build/bokftui`
- Restart daemon: kill the pid file's process, then
  `BOKFD_BACKUP_DIR=$HOME/bokf-demo/backup \
   BOKFD_EXPORT_DIR=$HOME/bokf-demo/export setsid nohup \
   ./build/bokfd --db $HOME/bokf-demo/bokfd.db \
   --socket $HOME/bokf-demo/bokfd.sock > $HOME/bokf-demo/daemon.log 2>&1 &`
- The user's own early instance was `/tmp/x.db` + `/tmp/bokfd.sock`
  (schema v1, old binary) — recreate or migrate it with the current build if
  it is still wanted.
- TUI smoke tests: drive over a pty with `script -qec`; function-key escape
  sequences are timing-sensitive there (not an app bug). Arrows arrive as
  application-mode sequences (`ESC O B` for Down), not `ESC [ B`, because
  curses enables the keypad. `Ctrl+N/C/F` are single bytes and reliable.
  Always wrap the run in `scripts/tui-sandbox.sh -- ./build/bokftui ...`: it
  isolates `XDG_CONFIG_HOME`/`XDG_CACHE_HOME` so a test can never overwrite
  the real `~/.config/bokf/tui.conf` or `~/.cache/bokf/tui.log`.

## Known caveats

- Saving with Ctrl+Enter needs a terminal that speaks xterm
  `modifyOtherKeys` level 2 or the Kitty keyboard protocol; gnome-terminal/VTE
  sends neither, so the hints advertise `F9`, which works everywhere.

- Developer tooling: the `g_cmd_<domain>[]` tables in `src/cmd_*.c` carry
  declarative argument schemas (`CMD_ARGS`); `describe` emits them and the
  dispatcher validates before the handler runs. `make check` (part of
  `make test`) fails when a command or error code is missing from
  `PROTOCOL.md` (`scripts/check-consistency.sh`) or when the generated
  command catalogue is stale (`make gen-protocol`). `make test-asan`/
  `test-ubsan` build `test_core` with sanitizers; `make test-pty` runs
  `scripts/tui-golden.py` against a throwaway `/tmp` daemon; `make gate`
  is the pre-push check (clean `-Werror` build in `build-gate/` + tests +
  ASan).
- Never commit unless the human asks.
- SQLite files must not be backed up live with restic; use
  `backup.snapshot` (`VACUUM INTO`) and point restic at the snapshots.
- Schema version is 11 (v3 moms rules; v4/v6 year info; v5 org
  description/shares + board members; v7 attachments append-only triggers;
  v8 bank reconciliation; v9 invoicing + widened `vouchers.source` with a
  table rebuild; v10 payroll + `payroll`/`payroll_tax` sources, same
  rebuild; v11 `employees.email`); forward migrations are in `db.c`.

## Makandra driftstatus (org 2)

- **Org**: Makandra AB, org 2. Räkenskapsår (id): 2022=3, 2023=4, 2024=5,
  2025=6, 2026=7, **2027=2 (öppet, aktuellt)**. Bokslut/AR/deklaration görs
  för det år som är valt i sessionen.
- **FK2027**: importerade Kapitas-böcker + 28 bokförda verifikat (V21–V48)
  för bank/skatt maj–sep 2026, samt V49 som makulerar en dubblett (V20).
  1930 stämmer mot banken utom **CDON 2 409 kr** (väntar på kvittots del
  2–4; bokförs när det kommer). 1630 = 40 721 (exakt enligt Skatteverket).
- **Underlag**: 279 attachment i org 2 (alla historikdokument + insamlade
  underlag). Bank-/SKV-utdrag ligger i `~/Makandra AB/{bank,skatteverket}`
  (Syncthing), källkorpus i `~/Downloads/Makandra AB-…/Bokföring/`.
- **Stängning**: 2022–2026 ska stängas av ägaren via **Räkenskapsår** i
  TUI:n; låt FK2027 vara öppen till nästa bokslut.
- **Deklaration**: FK2026 är deklarerad av revisorn. FK2027 deklareras
  våren 2027 (INK2/SRU via Bokslutshubben → Inkomstdeklaration).
- **Årshäftet**: fylls i Bokslutshubben (händelser, stämma, utdelning +
  datum, medelantal, noter). OBS: `dividend_ore` för FK2027 kan vara ett
  testvärde (10 000) — kontrollera före AR/deklaration.
- **Beslut/regler från bokföringsarbetet**: inga bokföringar utan
  godkännande; låsta år förblir låsta (rättelser görs i aktuellt år); SIE-
  importören ändras inte och importerad data "manipuleras" inte;
  historikårens P&L nettar noll pga källsystemets stängningar (AR hoppar
  över "Stäng"-verifikat i flerårsöversikten); utdelning bokförs vid stämman
  med mallen **Utdelning** (D 2099/K 2898); pappersoriginal finns i fysisk
  pärm (får refereras i efterhand, även i stängda år).
- **Lön (2026-09-21)**: bara ägaren är anställd, men schema och kommandon är
  fleranvändarklara. Lönemotorn (schema v11: anställda, skattetabeller,
  lönekörningar, lönebesked + mejl) och TUI-sektionen Lön är klara, men
  **ingen anställd är registrerad än** (personnummer, lön, skattetabell och
  kolumn fylls i under Register → Anställda). Konton enligt historiken:
  7210/7510/2710/2731/1630. Skattetabellerna hämtas med en knapp från
  Skatteverket (varning när året är gammalt), personnumret är krypterat i
  databasen. Ingen semesteruppbokning; arbetsgivardeklarationen (AGI) görs
  manuellt med underlaget från `payroll.agi`.