aboutsummaryrefslogtreecommitdiff
path: root/docs/STATE.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/STATE.md')
-rw-r--r--docs/STATE.md112
1 files changed, 112 insertions, 0 deletions
diff --git a/docs/STATE.md b/docs/STATE.md
new file mode 100644
index 0000000..d9edcb0
--- /dev/null
+++ b/docs/STATE.md
@@ -0,0 +1,112 @@
+# bokf — project state
+
+Snapshot for resuming work in a new session. Read with `AGENTS.md` (rules)
+and `docs/TUI-GUIDELINES.md` (UI conventions). Dated 2026-09-17.
+
+## Status
+
+Working self-hosted bookkeeping system, not production-proven. Backend ledger
+core is complete; filing/year-end/payroll are not. TUI is usable and
+exercised via pty smoke tests; the test suite (`make test`) covers the
+server/protocol/ledger only.
+
+## Locked decisions
+
+1. **Name/license**: `bokf`, daemon `bokfd`, clients `bokfctl` (scriptable)
+ and `bokftui` (ncurses); GPL-3.0-or-later; repo `~/work/bokf`.
+2. **Stack**: C11, Makefile, vendored SQLite 3.53.4 / yyjson 0.13.0 / Argon2
+ 20190702 / SHA-256 (public domain). Only system dep: libncursesw.
+3. **Storage**: SQLite WAL, `synchronous=FULL`, STRICT tables, composite-key
+ tenant isolation, append-only triggers, `VACUUM INTO` snapshots. Postgres
+ deliberately rejected for now; keep DB access behind one layer for a later
+ port.
+4. **Protocol**: NDJSON over Unix socket (+ optional token TCP), protocol v1.
+ `dry_run` on every mutation, `client_ref` idempotency, stable error codes,
+ `describe` + `agent.instructions`, money in integer öre.
+5. **Auth**: multi-org; memberships owner/bookkeeper/viewer; API tokens bound
+ to user+org with scopes, shown once, revocable; sessions in memory;
+ Argon2id. Server messages English, UI Swedish.
+6. **Compliance design**: SHA-256 audit chain, SHA-256 voucher chain
+ (canonical encoding in `SCHEMA.md` §7.1/§9.1), period locks, fiscal year
+ close, corrections only as ändringsverifikat, SIE 4 (CP437) in/out.
+7. **Verifikat ids**: series is free text (`A`, `V-`, `A ` …); unbroken
+ numbering per fiscal year+series; id displayed as `series+number`
+ (`V-8`). Org setting `default_series` (Inställningar) for new vouchers and
+ new templates.
+8. **Templates** (`konteringsmallar`): server-side; formula language over `x`
+ with `+ - * /` and parentheses, positive=debit, negative=credit, zero rows
+ dropped; rounding remainder assigned to the largest row; `{x}` in the
+ description; `template.*` commands + `voucher.post {template,x}`; archive
+ instead of delete.
+9. **Ingående balans**: one series `IB` voucher per fiscal year (dated at
+ year start). Reports treat series IB as IB, not period movement; SIE
+ export/import round-trips without double counting; TUI editor posts only
+ deltas so nothing is ever edited.
+10. **Attachments**: content stored in the DB (BLOB), immutable, linked via
+ append-only `voucher_attachments`. Default limit 10 MiB
+ (`max_attachment_bytes`); the socket line limit is derived from it
+ (base64). TUI `Ctrl+F` attaches via file browser; the client checks the
+ size from `meta` first. Setting `attachment_dir` (tilde expanded).
+11. **UI keys**: Ctrl+N = add, F5 = refresh, Esc/q = back (never exits),
+ Ctrl+C = quit, 1–9/g = jump, F7 = clear row in editors, F9 = save.
+ Shared line editor and date field; see TUI-GUIDELINES.md.
+12. **Login**: two steps — credentials, then org picker ("Välj organisation
+ att representera"). No org switch in the dashboard; fiscal year switch is
+ on the dashboard. `--org ID` bypasses the picker.
+13. **Settings**: `settings.get`/`settings.set`; keys `default_series`,
+ `attachment_dir`.
+
+## Pending decisions
+
+- Link attachments after posting (API already supports
+ `attachment.put {voucher_id}`): proposed TUI actions — `Ctrl+F` in the
+ voucher detail to upload+link, and selecting an inbox item and pressing a
+ key to link it to a voucher picked from a list. Waiting for a go-ahead.
+- Priority between **eSKD moms filing** and **bokslut/K2+SRU** for the next
+ backend milestone (eSKD was suggested first).
+- Moms `report_rules` seed is a reviewed starter mapping only; must be
+ checked against the current Skatteverket blankett before filing.
+
+## Backlog (prioritized, from COMPLIANCE.md §10 and the audit)
+
+1. eSKD file generation for momsdeklaration.
+2. Bokslut automation (avskrivningar, periodiseringsfond, skatt,
+ resultatdisposition).
+3. K2 årsredovisning document + SRU files (INK2/INK2R/INK2S).
+4. `audit.verify` must also verify the **voucher** hash chain (today only the
+ audit chain is verified).
+5. `report.general_ledger` and `report.voucher_list` (documented, not
+ implemented).
+6. `describe` argument schemas (currently name/summary/permission only).
+7. Pre-migration `VACUUM INTO` snapshot (promised in SCHEMA.md, not built).
+8. Docker image + compose (multi-arch amd64/arm64, GHCR) and systemd unit.
+9. Password change, user disable, TOTP.
+10. Bank import/reconciliation (CSV first, then PSD2), invoicing/reskontra,
+ AGI/payroll if employees.
+11. SIE import only into an empty fiscal year; consider broader import.
+12. TUI polish: horizontal scrolling in long text fields, bracketed paste.
+
+## Environment / how to run
+
+- 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). `Ctrl+N/C/F` are
+ single bytes and reliable.
+
+## Known caveats
+
+- 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 2; forward migrations are in `db.c`.