configuration-and-data.md 7.7 KB


type: operations title: Configuration and data files description: How src/config.rs loads config.toml, the supported keys and defaults (including ai_retries and web_port), the template file, where the data directory and databases live, and operational and security caveats. tags: [configuration, toml, data-directory, sqlite, security] sources:

  • id: openwiki-source-ea70eb6c04 resource: repo://.gitignore
  • id: openwiki-source-0d5b861992 resource: repo://config.toml.global.template
  • id: openwiki-source-1b05507d70 resource: repo://src/ai.rs
  • id: openwiki-source-2a737474d8 resource: repo://src/config.rs generated: { by: "claude-code", at: "2026-10-20T20:27:06.515Z" } verified:
  • by: openwiki/0.7.2 at: 2026-10-20T20:27:06.515Z ---

Configuration and data files

All runtime settings come from one TOML file loaded by Config::load (src/config.rs:259-263). No environment variable is ever read (src/config.rs:1-25).

Data directory

The data directory is fixed: <platform config dir>/wh, resolved with dirs::config_dir() (src/config.rs:166-170). On Windows this is %APPDATA%\wh. It cannot be changed from the config file. At startup ensure_data_dir creates it if missing (src/config.rs:293-296).

File Purpose Defined by
config.toml Optional settings CONFIG_FILE, src/config.rs:56
session.db WhatsApp session store used by whatsapp-rust (WhatsApp client) session_db_path, src/config.rs:302-304
history.db Local messages, chats, contacts, per-chat autoreply flags and the global autoreply setting (History store) history_db_path, src/config.rs:310-312
ai_requests.log Optional AI request log, written only when ai_log = true (AI client) ai_log_path, src/config.rs:318-320

The two databases are separate by design: session.db belongs to the WhatsApp library (linked-device session and keys, schema owned by whatsapp-rust), while history.db belongs to the app (chats, messages, contacts, autoreply flags).

Keys

Key Purpose Default when missing or blank
openai_api_key Bearer token for the AI endpoint (trimmed) none — the AI client cannot be built
openai_base_url Base URL of the OpenAI-compatible endpoint (trimmed, trailing / removed) https://ollama.com/v1
openai_model Model for text replies (trimmed) deepseek-v4.1-flash
openai_vision_model Model for image replies (trimmed) none — image understanding disabled
system_prompt Persona/instructions for autoreplies, kept as written (not trimmed, multiline allowed) none — AI not configured
ai_log Boolean; when true every request sent to the AI model is appended to ai_requests.log false
cooldown_seconds Minimum seconds between autoreplies in a private chat or to a group message addressed to the user; 0 disables it 30
group_cooldown_seconds Same, for group messages not addressed to the user; 0 disables it 300
catch_up_seconds After a restart, the last unanswered message of each private chat is answered once if it is at most this old; 0 disables the catch-up 7200
ai_retries How many times a failed AI request is retried, waiting 2 s, 4 s, …; HTTP 4xx other than 429 is never retried; 0 disables retrying 2
web_port TCP port of the web control panel on 0.0.0.0, no authentication; valid range 1–65535 unset — panel disabled

Mapping and defaults: Config::from_file (src/config.rs:269-287) and the constants at src/config.rs:34-45. The timing keys and ai_retries are unsigned integers in the file (Option<u32>, src/config.rs:121-128), so a negative value is rejected as an invalid value type; the timing keys are stored as i64 in Config. web_port is Option<u16> (src/config.rs:129-131), so negatives and values above 65535 fail TOML parsing, and resolve_web_port (src/config.rs:243-252) additionally rejects 0. Their use is described in AI autoreply, AI client and Web control panel. The binary embeds no prompt text: without system_prompt the AI is not configured and the status line says so (see Application state). Unknown keys are ignored.

config.toml.global.template in the repository root lists every key with its default and a comment (with web_port commented out); copy it to the data directory as config.toml and fill in openai_api_key and system_prompt.

Loading rules

  • Missing file → all defaults (read_config_file, src/config.rs:202-212).
  • Unreadable file → cannot read config file <path>.
  • Invalid TOML or wrong value type → invalid config file <path> with the cause invalid TOML syntax or value type at line L, column C; the error never echoes file content (parse_config_file, src/config.rs:187-196). This also covers negative or non-integer timing keys and ai_retries, a non-boolean ai_log and an out-of-range web_port.
  • A leading UTF-8 BOM (common with Windows editors) and CRLF line endings are tolerated.
  • openai_base_url consisting only of slashes is rejected with openai_base_url in config.toml must not be empty or only slashes (src/config.rs:234-241).
  • web_port = 0 is rejected with web_port in config.toml must be between 1 and 65535.

Startup aborts with cannot load configuration on any of these errors (Runtime).

Security and operational notes

  • The API key is never printed: Config's Debug shows *** or <unset> (src/config.rs:134-160), and the raw FileConfig has no Debug impl at all (src/config.rs:105-132). The AI client redacts it too.
  • ai_requests.log never contains the API key and replaces image data with a size placeholder, but it does store the full request (system prompt and chat context) and the reply in clear text, one record per attempt including retries, and it is only appended to, never rotated. Enable ai_log only for diagnosis and delete the file afterwards.
  • web_port exposes an unauthenticated HTTP panel on every network interface: anyone who can reach the port can see chat names, toggle autoreplies and quit the bot. Set it only on a trusted network or firewall the port. A port already in use aborts startup with cannot start web server on port <port>.
  • Keep config.toml in the data directory, outside the repository. .gitignore ignores a root-level /config.toml and .env (.gitignore:4-6), as well as SQLite journal/WAL/SHM files; note that the *.db pattern is commented out (.gitignore:7), so databases copied into the repo would not be ignored.
  • session.db holds the linked-device credentials: deleting it forces a new QR pairing. history.db can be deleted to reset local history and the per-chat and global autoreply flags; it is recreated on start.
  • Images downloaded for vision replies are kept in memory only and never written to the data directory.

Tests

src/config.rs:323+ covers defaults, full files, blank values, multiline prompts, trimming, base URL normalisation and errors, Debug masking, vision model, DB and AI log paths, ai_log, cooldown, catch-up and ai_retries defaults, custom values (including 0) and rejection of negatives, web_port (unset, valid, 0 and out-of-range rejected), unknown keys, BOM/CRLF, non-leaking parse errors, missing, existing, invalid and unreadable files. See Unit tests.