Tests define the db module API:
- connection_url() builds the sqlx URL with percent-encoded
credentials; with/without the database name
- split_statements() splits SQL on semicolons outside strings and
line comments (the embedded migration is applied statement by
statement, since DDL cannot run in a rollbackable transaction)
- the embedded migration is Documentation/schema.sql (version 1),
carrying the seven domain tables only; schema_migrations is
created by the application
- backup_command() shells out to mariadb-dump (mysqldump fallback)
with --single-transaction, password via MYSQL_PWD, never argv
- restore_command() pipes the dump (which carries CREATE DATABASE /
USE) into the mariadb client
- backup_filename() is timestamped per cli.md
- Config::load / load_with read the TOML file; port fields accept
either a TOML int or a string (real configs use both)
- empty strings resolve to defaults: db 3306, web 8080,
$HOME/.config/rpn state dir, <state>/backups backup dir; an
explicit state dir steers the backup default
- show() masks the password; validate_database() enforces
host/user/name for commands that touch the database
- resolve_config_path() implements the documented lookup order
Tests define the API for the config module:
- Config::load_with(path, home) / Config::load(path) read the TOML file
(database/web/state/backup sections per config.template.toml)
- empty strings resolve to built-in defaults: db port 3306, web port
8080, state dir $HOME/.config/rpn, backup dir <state>/backups
(backup follows an explicitly set state dir)
- port may be written as a TOML int or a string in real configs;
non-numeric strings are a ConfigError
- resolve_config_path(): --config flag > $RUSTYRPN_CONFIG >
cwd/config.toml; --env=dev|test only affects that last default slot
- Config::show() renders the effective config with the password masked
- Config::validate_database() requires host/user/name
Also adds the toml crate (forced by the TOML config decision).
First code in the repo. Workspace root is Application/ per readme;
members are src/core (crate rpn-core) and src/cli (binary rpnc).
Crate names are prefixed to avoid clashing with the std `core`
crate; directory names follow the readme layout.
Dependencies (versions pinned in Cargo.lock):
- core: sqlx (mysql, runtime-tokio, chrono, rust_decimal), chrono,
csv, thiserror, serde/serde_json, tracing, plus sha2 (SHA-256
file checksums required by schema.sql), rust_decimal (exact
DECIMAL(10,2) money, forced by the "money is DECIMAL
everywhere" decision), tokio and tempfile as dev deps.
- cli: clap (derive), tokio, tracing-subscriber (env-filter),
anyhow, serde/serde_json, chrono, csv.
The extra crates beyond the readme stack (sha2, rust_decimal,
tracing-subscriber, tempfile-dev) are direct consequences of
already-committed decisions; flag for maintainer review.
No feature logic yet: rpnc is an empty shell, the domain modules
land in the TDD slices that follow.