Commit Graph
8 Commits
Author SHA1 Message Date
hermes e7acfcf899 chore: apply cargo fmt to core crate
config.rs had two single-line struct variants and a let-chain that
rustfmt (edition 2024) wants expanded; db.rs test module picked up the
same treatment. Whitespace-only - no behaviour change.

Why: 'cargo fmt --check' is part of every task's definition of done,
and main was handing over slightly dirty.
2026-10-08 12:38:56 +02:00
hermes 3f0974a1d1 data: add sanitized test fixtures and their generator
Real samples under data/test_input/ stay local and gitignored; these
committed fixtures are format-identical copies with every identifying
value replaced one-way via salted hashes: epsilon contract cards and
customer numbers into synthetic disjoint ranges (batches renumbered
9405+, dates +2y; cumulative slice batches 5001+, dates -6y), tsdrms
R/A / DBR / location ids into ZZ-form synthetic ids (dates +2y,
filenames shifted to match cutoffs), subfranchise statements to
extracted text with sender, partner, invoice numbers and amounts
replaced (EUR x rate = SEK arithmetic deliberately NOT preserved).
Amounts, GL codes, descriptions, and station/terminal/pump/receipt
numbers carry no personal data and are kept verbatim per readme
'Data formats'.

scripts/sanitize_samples.py regenerates fixtures deterministically
from local raw samples; scripts/check_fixture_leaks.py verifies no
real value appears in fixtures (content or filenames), exit 0 =
clean. Verified passing for all sources.
2026-10-08 11:30:13 +02:00
jakob 676e55eeb6 db: add failing tests for connection URL, migration splitting, backup/restore
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
2026-09-08 21:38:48 +02:00
jakob 9452962c1c config: implement loading, defaults, masking, and validation
- 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
2026-09-08 18:49:52 +02:00
jakob a81dd6f543 config: add failing tests for load, resolution, defaults, masking
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).
2026-09-08 18:17:00 +02:00
jakob e81ef6b351 workspace: scaffold Cargo workspace with rpn-core and rpn-cli
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.
2026-09-08 17:56:45 +02:00
jakob 2a0bba5be7 Add web, state, and backup sections to config template
- [web]: port and public fqdn for the daemon (Caddy proxies from a
  separate jail); port defaults to 8080
- [state]: daemon pidfile and logs directory, default ~/.config/rpn
- [backup]: timestamped dumps for rpnc db backup, default
  ~/.config/rpn/backups; rpnc db restore looks here by default
- cli.md: document the optional positional path and the directory
  defaults for db backup/restore
2026-09-02 11:37:04 +02:00
jakob 77354d4ba8 Add config.template.toml 2026-08-25 13:11:24 +02:00