Files
RustyRPN/Documentation/roadmap.md
T
hermes a350afc053 docs: split roadmap out of readme into Documentation/roadmap.md
The readme served two roles: design-decision source of truth and
work-status tracker. The status section grew into a plan the
orchestrator must navigate, so it moves to its own file with task
IDs, dependency edges, statuses, and per-item acceptance criteria.

readme.md remains authoritative for decisions (stack, formats,
workflow); workflow step 7 and AGENTS.md pointers now name
roadmap.md for status. Cross-references verified.

Also records: stale feature/epsilon-parser branch pointer (676e55e,
2 behind main) deleted locally; recreate from main when B1 starts.
2026-10-08 12:35:58 +02:00

6.2 KiB
Raw Blame History

Roadmap and status of functionality

This file is the roadmap. Design decisions that a roadmap item depends on are still owned by readme.md (the source of truth); this file tracks what is done, in flight, and planned, with status, dependencies, and acceptance criteria per item.

Status legend:

  • ✅ done — implemented, tests green, merged to main
  • 🔴 red — tests committed and failing (TDD in progress)
  • 🟡 spec — specified, no code or tests yet
  • ⚪ idea — planned, not specified
ID Area Item Status Depends on
A1 core config: load, resolve, defaults, mask, validate ✅ —
A2 core db: connection URL, migration split/embed, backup/restore 🔴 A1
B1 core+cli epsilon parser: file → rows → batch aggregates 🟡 A2
B2 cli file import / file list: ingest + idempotency 🟡 B1
B3 cli customer / card CRUD (batch, card, customer) 🟡 A2
B4 cli invoice creation from batch data (invoice prepare) 🟡 B2, B3
C1 core tsdrms xlsx parser (GL journal, cutoff partitioning) ⚪ A2
C2 core subfranchise PDF statement parser ⚪ A2
D1 core Fortnox voucher mapping (port spreadsheet → TOML) ⚪ C1
E1 server axum API + sessions + roles ⚪ A2
E2 web Leptos SPA (invoice portal for rental firms) ⚪ E1
F1 cli daemon start/stop/status ⚪ E1
G1 spa receipt reissue (retail fuel, by date + last4) ⚪ E2
G2 spa to-do application for employees ⚪ E1
G3 core car registry (owned/leased, costs, besiktning, status) ⚪ A2

Track A — foundations

A1 core/config ✅

Loading (--config flag → $RUSTYRPN_CONFIG → ./config.toml, --env selects dev/test variants in the last slot only), built-in defaults, secret masking for config show, validation. Tests green (commit 9452962).

A2 core/db 🔴 — next task

12 unit tests committed red (commit 676e55e): connection_url (percent-encoded credentials, with/without database), split_statements (comment/string-aware), MIGRATION_V1 (embeds Documentation/schema.sql as v1), backup_command / restore_command (mariadb-dump/mariadb via MYSQL_PWD, never argv), backup_filename (timestamped). Scope: implement minimal green path. Pure functions — no live database, no new dependencies. Do not alter the tests' intent. Accept: cargo test green workspace-wide; fmt + clippy clean.

Track B — fuel station data (epsilon)

B1 epsilon parser 🟡

Branch feature/epsilon-parser to be created from main when work starts (a stale earlier pointer was deleted 2026-10-08). Workflow step 2 (spec + test checklist agreed with maintainer) is pending — no failing test may be written before it. Fixtures ready: data/fixtures/epsilon (batches 9405–9412, cumulative slice). Sketch: 16-field TSV per readme §Data formats; filename batch number must match every row; M/d/yyyy h:mm:ss AM/PM dates; rust_decimal amounts; Quality 0 zero-value rows preserved; batch aggregates (totals per quality, row count, date range) for the batches table.

B2 file ingest & idempotency 🟡

files table: filename = natural key + content hash (sha2, already a core dep). Re-ingesting the same file must be a no-op. Open decision (maintainer): test against scratch MariaDB vs mocked repo layer. Open decision: Amount == Volume × Price — hard error or reported warning.

B3 customers & cards 🟡

Contract cards = epsilon rows with non-empty customer number; stored unmasked as delivered (personal data rule: schema.sql / cli.md). CRUD per Documentation/cli.md; delete blocked while referenced.

B4 invoice creation 🟡

From batch/card data into invoices + invoice_items; Fortnox export format TBD (depends on D1 decision).

Track C — rental data (tsdrms / Enterprise)

C1 tsdrms xlsx parser ⚪

GL journal (double-entry pairs), calamine-class crate needed — ask before adding dependency. Critical quirk: monthly files partition by Cutoff Date, not Transaction Date. Floats round to 2 decimals on ingest. Fixtures ready: data/fixtures/tsdrms.

C2 subfranchise PDF parser ⚪

Text-based 1-page statements; PDF text-extraction crate chosen when the feature starts. Parse defensively (layout verified on 6 samples only); European number format incl. (x,yy) negatives; line items by pattern, not exact string. Fixtures ready as extracted text: data/fixtures/subfranchise.

Track D — bookkeeping

D1 Fortnox voucher mapping ⚪

First task is porting the Apple Numbers mapping (data/other_resources/, gitignored — read, never modify) into a versioned TOML table in-repo before writing code against it. Depends on C1 data model.

Track E — server & SPA

E1 axum API ⚪

JSON API, argon2id login, MariaDB-backed sessions behind HttpOnly/Secure/SameSite=Lax cookie, rate-limited, no user enumeration, roles director/employee/customer (customer queries scoped to session's company). New deps (axum, sqlx already partly in place) — ask before adding.

E2 Leptos SPA ⚪

Served by the same binary as the API.

Track F — deployment

F1 daemon 🟡→⚪

rpnc daemon start|status|stop per cli.md (pidfile + logs under state dir; local-only status checks). Caddy reverse proxy and FreeBSD jail packaging are out of scope for the repo (readme §Technology).

Track G — later features

G1 receipt reissue ⚪ (low priority)

Identify by date + last 4 (masked consumer cards make last4 available); render template; e-mail to customer.

G2 employee to-do app ⚪

G3 car registry ⚪

Owned/leased cars, per-car costs, besiktning tracking, status (active/broken/repair), tyre seasons.

Near-term ordering

  1. A2 → green baseline for everything.
  2. B1 spec discussion (maintainer gate) → B1 → B2 → B3 → B4: the fuel-sales vertical slice usable from the CLI.
  3. C1/C2/D1 extend into rentals + bookkeeping.
  4. E/F make it multi-user; G fills in.

Maintenance rules

  • Every task updates this file in its own branch (workflow step 7); decision changes go to readme.md in the same commit.
  • Status changes commit with the merge, not before.
  • AGENTS.md §Current state must agree with this file; update both.