Files
cproof-context/gotchas.md
jabber.developer2 22977846a3 docs: split context into layered, agent-oriented files
Replace the single file-structure.md with a stratified layout designed
for AI/agent skill consumption: tables and concrete identifiers over
prose, files loaded on demand, content separated by churn rate.

Layers:
- architecture/  stable structural reference (overview, source-map,
                 test-map, data-flow)
- patterns/      memory, commands, autocomplete, events, xmpp,
                 encryption, ui, plugins
- testing/       unit-tests, stubs, functional-tests, bench
- build/         local, docker, ci
- playbooks/     add-command, add-test, add-autocomplete,
                 add-event-handler, add-encryption
- gotchas.md     append-only dated entries (seven seed entries)
- wip/           branch-specific notes; deleted on merge to master

Stable layers describe cproof on master only. In-flight feature
branches (currently feat/ai) get a single file under wip/.

INDEX.md is the entry map with churn labels; SKILL.md is the
always-loaded skill hint pointing to it.
2026-04-30 20:52:06 +03:00

115 lines
3.5 KiB
Markdown

# Gotchas
Append-only log of known pitfalls. One entry per pitfall. Format:
```
## YYYY-MM-DD — <short title>
<body — what bites, why, what to do instead>
```
Scan this file before finishing any non-trivial task.
---
## 2026-04-30 — `g_strsplit` result must use `g_strfreev`
`g_strsplit` (and `g_strdupv`) return a `gchar**` whose elements are
individually GLib-allocated. Free with `g_strfreev`, **not** `g_free`. The
latter compiles fine and silently leaks the inner strings.
The cleanup macro is `auto_gcharv` (declared in `src/common.h`):
```c
auto_gcharv gchar** parts = g_strsplit(line, " ", -1);
```
Mixing `g_free` on a `gchar**` is the most common allocator-mismatch bug in
this codebase.
---
## 2026-04-30 — `JABBER_CONNECTED` must be queued in unit tests
Most XMPP-touching code paths gate on `connection_get_status()`. The unit-
test stub returns `mock()`, so every test reaching that gate must:
```c
will_return(connection_get_status, JABBER_CONNECTED);
// or
will_return(connection_get_status, JABBER_DISCONNECTED);
```
Forgetting this aborts cmocka with a "missing mock value" error. If you see
that error, it's almost always `connection_get_status` you forgot.
---
## 2026-04-30 — Autocomplete callbacks must be stateless
Some older callbacks keep "last match" state in a file-static `_last_*_match`
variable. Do not copy that pattern. A clean canonical example is
`roster_contact_autocomplete` (`src/xmpp/roster_list.c`) — it delegates
straight to `autocomplete_complete` against a roster-owned `Autocomplete`
object and keeps no callback-local state.
Stateful callbacks misbehave under shift-tab cycling and break when two
completers run concurrently in a layered command (e.g. `/foo set bar <tab>`
followed by `/foo set baz <tab>`).
---
## 2026-04-30 — CWE-134 format-string discipline
Never pass user-controlled or arbitrary strings as the format argument to
`printf`-family or GLib formatted-print functions. A recent compiler-
hardening pass (cf. cproof commit `9ec01fa8c`) audited and tightened these
sites; do not regress.
Right:
```c
cons_show("%s", user_text);
```
Wrong:
```c
cons_show(user_text);
```
The compiler does not always warn, especially across helper layers. Enable
and respect `-Wformat -Wformat-security` warnings in any build you trust.
---
## 2026-04-30 — Build inside Docker, not on the host
Library version drift between a developer host and `Dockerfile.debian`
(GLib, OpenSSL, libstrophe in particular) can mask or invent failures. CI
is the source of truth; CI builds inside the Debian image. See
`build/docker.md`.
If you absolutely must build on the host, mirror the package set in
`Dockerfile.debian` exactly and pin versions — you will spend more time
chasing version drift than the Docker build would have cost.
---
## 2026-04-30 — Beware of "Profanity" vs "cproof" naming
The fork-rename is incomplete. Many files, symbols, copyright headers, and
config keys still say `Profanity` / `prof_` / `profanity`. These are
authoritative as-is; do **not** rename them opportunistically alongside
unrelated changes. Rename work, when it happens, will be a dedicated PR.
---
## 2026-04-30 — Encryption disable builds must compile
Each encryption stack (`HAVE_OMEMO`, `HAVE_LIBOTR`, `HAVE_LIBGPGME`) can be
turned off at `configure` time. New code that calls into these modules
must wrap calls in the matching `#ifdef` and provide a graceful fallback
in the `#else`. CI does not always test every disable combination — verify
locally with at least the off-build for each stack you touched.