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

148 lines
6.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.