summaryrefslogtreecommitdiff
path: root/AGENTS.md
blob: e54f786c23d56df61113c8de51fc092ed61c1c26 (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
# AGENTS.md — working on bokf

`bokf` is a self-hosted Swedish bookkeeping system in C11: one daemon
(`bokfd`) owning a SQLite database, one JSON protocol, three clients
(`bokfctl`, `bokftui`, agents). GPL-3.0-or-later.

## Build and test

```sh
make -j$(nproc)      # bokfd, bokfctl, bokftui
make test            # server/protocol test suite — must be green before you stop
```

No new dependencies without asking. SQLite, yyjson, SHA-256 and Argon2 are
vendored in `vendor/` and pinned; the only system library is libncursesw.

## Layout

| Path | What |
|---|---|
| `src/` | daemon, protocol, ledger, reports, SIE, seed, formula |
| `clients/` | `bokfctl.c`, `bokftui.c`, shared `client.c` |
| `docs/` | PROTOCOL.md, SCHEMA.md, COMPLIANCE.md, TUI-GUIDELINES.md |
| `tests/` | in-process protocol/ledger tests (`test_core.c`) |
| `data/` | BAS charts (third-party, see THIRD_PARTY_NOTICES.md) |

## Invariants — do not break these

- **Protocol first.** All state changes go through commands in `PROTOCOL.md`;
  clients never touch the database or bypass the daemon.
- **Amounts are integer öre**, dates `YYYY-MM-DD`, account numbers strings.
- **Append-only ledger.** Vouchers/rows/audit are immutable; corrections are
  new vouchers. Never add an UPDATE/DELETE path for them.
- **Everything is audited** via `audit_append`; secrets never reach the log.
- **Tenant isolation**: every tenant table carries `org_id`, references are
  composite FKs. New tables follow the same pattern.
- **Hash chains**: if you change what a voucher stores, check the canonical
  encodings in `SCHEMA.md` §7.1/§9.1 and `ledger.c`.

## Changing the schema

Bump `BOKF_SCHEMA_VERSION` in `db.h`, add a forward migration in `db.c`, update
`SCHEMA.md`, and make sure an existing test database upgrades (the test suite
opens a fresh DB; migration is exercised by running the daemon on the demo DB).
Never rewrite ledger rows in a migration.

## Adding a command

1. Handler in `commands.c` (or the domain file it belongs to), using the
   `fail()/failf()` helpers and stable error codes from `PROTOCOL.md` §5.3.
2. Entry in `g_commands[]` with permission, `need_org`, `mutating`, `dry_run`.
3. Audit (`audit_append`) for mutations, after success.
4. Update `docs/PROTOCOL.md`; add tests in `tests/test_core.c`.
5. `agent.instructions` in `commands.c` if agents need to know about it.

## Server code style

C11, no comments unless the reason is non-obvious, static helpers, no VLAs.
Bounded buffers with `snprintf`, check every `sqlite3_step`, free what you
allocate with a clear owner. Warnings must be zero (`-Wall -Wextra …`).
User-visible server messages are English; the TUI is Swedish.

## TUI work

Read `docs/STATE.md` first for status, locked decisions, pending decisions
and the prioritized backlog. Then read `docs/TUI-GUIDELINES.md` and follow it. Summary: one shared line editor,
universal keys (Ctrl+N new, F5 refresh, Esc/q back, digits jump, `g` goto),
forms behave the same everywhere, hints always visible, errors shown as
`CODE: message`. Prefer reusing the shared helpers (`select_list`, `menu`,
`field_edit`, `pad_field`, `message`, `show_error`) over new local loops.

## Verifying

- Server changes: `make test`. UI changes: also drive `bokftui` over a pty
  (`script -qec`) or against the demo daemon and check the real behaviour.
- Never commit unless the human asks. When asked, keep the message short and
  in the repo's style.