Local application and operations rehearsal completed
Supplier catalog imports
A CSV review app that shows price and part changes before applying an approved batch to a SQLite catalog.
Implementation
Supplier CSVs are retained with their source digest, parsed with an explicit monetary locale, and staged separately from the current catalog. The review shows added, changed, unchanged, missing and rejected rows.
Approval checks the catalog version and review digest inside the write transaction. Competing reviews become stale; a fault during application rolls back the entire batch. Repeating a successful request returns the original result.
The dark browser interface includes role-based controls, original CSV and JSON report downloads, paginated reviews, and a catalog preview.
Checked online SQLite snapshots, restore into a new directory, and a periodic backup command are included. An executed operations rehearsal covers abrupt process exits, recovery and rejected inputs.
Inputs and assumptions
- Included ACME and EURO supplier records are synthetic. Missing source rows remain in the catalog.
- Item identity is supplier plus normalized part number. USD, EUR and GBP prices use integer cents; EA, BOX, KG and M units are explicit.
- Python 3.12 and local SQLite storage. SQLite serializes writers; the earlier PostgreSQL deployment plan is not included.
Recorded results

Machine-readable result summary
{
"workload": "New supplier; all rows added; synthetic prices and parts. One worker; SQLite FULL durability. Shared execution host, not a production capacity claim.",
"environment": {
"python": "3.12.14",
"sqlite": "3.53.1",
"system": "Linux-6.18.55-x86_64-with-glibc2.39",
"logical_cpus": 9
},
"measurements": [
{
"input_rows": 1000,
"stage_seconds": 0.0986,
"review_page_seconds": 0.009,
"commit_seconds": 0.0212,
"peak_python_allocations_mib": 1.19,
"source_bytes": 42934,
"written_rows": 1000
},
{
"input_rows": 10000,
"stage_seconds": 0.8935,
"review_page_seconds": 0.0953,
"commit_seconds": 0.2224,
"peak_python_allocations_mib": 12.0,
"source_bytes": 447934,
"written_rows": 10000
},
{
"input_rows": 100000,
"stage_seconds": 9.8779,
"review_page_seconds": 1.2236,
"commit_seconds": 2.4308,
"peak_python_allocations_mib": 120.49,
"source_bytes": 4578934,
"written_rows": 100000
}
]
}Verification
20 of 20 tests passed. Failures: 0. Errors: 0.
20 database and HTTP tests pass, including concurrent approvals, response retries, rollback after a row write, rejected CSVs and role checks. The sample workflow was also exercised in a browser. A separate operations rehearsal passes 14 expected-outcome checks, including process crashes, checked snapshots, restore and a finite backup schedule.
python tests.py python evidence.py python operations_rehearsal.py
Executed test cases
- test_ambiguous_decimal_and_extra_precision_rejected (__main__.DatabaseTests.test_ambiguous_decimal_and_extra_precision_rejected)
- test_concurrent_reviews_one_wins_other_is_stale (__main__.DatabaseTests.test_concurrent_reviews_one_wins_other_is_stale)
- test_currency_and_unit_change_remain_explicit_in_diff (__main__.DatabaseTests.test_currency_and_unit_change_remain_explicit_in_diff)
- test_duplicate_headers_and_unclosed_quote_are_blocked (__main__.DatabaseTests.test_duplicate_headers_and_unclosed_quote_are_blocked)
- test_duplicate_normalized_keys_reject_both_and_block_batch (__main__.DatabaseTests.test_duplicate_normalized_keys_reject_both_and_block_batch)
- test_explicit_european_decimal_mapping (__main__.DatabaseTests.test_explicit_european_decimal_mapping)
- test_full_report_includes_all_pages (__main__.DatabaseTests.test_full_report_includes_all_pages)
- test_invalid_unicode_is_rejected_without_server_error (__main__.DatabaseTests.test_invalid_unicode_is_rejected_without_server_error)
- test_mid_batch_fault_rolls_back_items_version_and_audit (__main__.DatabaseTests.test_mid_batch_fault_rolls_back_items_version_and_audit)
- test_newlines_in_quoted_description_are_retained (__main__.DatabaseTests.test_newlines_in_quoted_description_are_retained)
- test_quoted_csv_aliases_diff_and_missing_rows (__main__.DatabaseTests.test_quoted_csv_aliases_diff_and_missing_rows)
- test_refresh_changes_review_digest_and_requires_new_review (__main__.DatabaseTests.test_refresh_changes_review_digest_and_requires_new_review)
- test_response_loss_retry_returns_committed_result_once (__main__.DatabaseTests.test_response_loss_retry_returns_committed_result_once)
- test_source_digest_is_idempotent_and_bytes_preserved (__main__.DatabaseTests.test_source_digest_is_idempotent_and_bytes_preserved)
- test_http_authentication_csrf_origin_and_host_checks (__main__.HttpTests.test_http_authentication_csrf_origin_and_host_checks)
- test_http_full_review_and_download_workflow (__main__.HttpTests.test_http_full_review_and_download_workflow)
- test_http_importer_cannot_approve (__main__.HttpTests.test_http_importer_cannot_approve)
- test_http_path_traversal_is_not_a_file_route (__main__.HttpTests.test_http_path_traversal_is_not_a_file_route)
- test_http_reader_cannot_stage_or_approve (__main__.HttpTests.test_http_reader_cannot_stage_or_approve)
- test_http_static_page_and_malformed_input (__main__.HttpTests.test_http_static_page_and_malformed_input)
Run locally
Python 3.12+ / SQLite via Python standard library
python app.py --seed --port 8011 # Open http://127.0.0.1:8011 python tests.py python evidence.py python build_report.py python operations_rehearsal.py
Source and evidence
- Application and transaction rules
app.py - SQLite schema
schema.sql - Sample supplier update
fixtures/price-update.csv - Rejected-row example
fixtures/rejected.csv - Applied import evidence
results/applied-import.json - Measured CSV size sweep
results/size-sweep.json - Database and HTTP tests
tests.py - Operator guide
OPERATOR.md - Executed operations and recovery report
operations-report.html - Expected and observed operational outcomes
completion.json - Reproducible crash and recovery scenarios
operations_rehearsal.py - Checked SQLite backup and restore CLI
operations.py - Periodic snapshot runner
backup_schedule.py - Deployment, recovery and capacity assumptions
OPERATIONS.md
Limits
- Localhost-only reference app with fixed demo accounts and one-hour in-memory sessions. No production identity provider or TLS listener.
- Files are limited to 16 MiB and 100,000 rows. Parsing and diff storage are memory-bound; paginated review still loads the complete stored diff. Timings are measurements of this host, not capacity guarantees.
- No supplier API, automatic deletion, currency conversion or unattended import. Process-crash recovery and corrupted-snapshot rejection were executed; physical disk failure and power-loss behavior remain outside the model.