# Why SempreVenda has a Rust transaction core

> A grounded engineering note on SempreVenda's Rust core, SQLite command processor, receipts, offline queue, effects, tests, and unfinished migration work.

Source: https://agnaldoguerra.com/technical-note.html
This is the markdown edition of the page, generated from the page itself.
Every page as markdown: https://agnaldoguerra.com/llms.txt

## Contents

- [The current design](#the-current-design)
- [All writes use the same path](#all-writes-use-the-same-path)
- [Offline commands](#offline-commands)
- [External work](#external-work)
- [Evidence](#evidence)
- [Where it stands](#where-it-stands)

---

Engineering note · **SempreVenda** · 2026

I built SempreVenda v0 while running a bar and café. It handled tables, kitchen tickets, split bills, payments, cash drawers, stock, and reports.

The main problem was not missing features. It was that transaction rules existed in several places.

The browser could assemble a sale. Payment code could interpret its balance. Reporting code could reconstruct the result later. Fixing one path did not prove that the others behaved the same way.

That is why I stopped extending the original system and rebuilt the transaction path.

## The current design

`sv-core` contains the business rules. It is a Rust crate with no database, network, filesystem, clock, or random access.

It receives:

- the current state;
- a command;
- a context containing time, operating day, policy, actor, device, and generated IDs.

It returns either a decision or a domain error.

`stationd` runs the local Station. It owns SQLite, authentication, the LAN API, and all writes. The React application sends typed commands through a generated TypeScript client.

The browser does not decide transaction outcomes.

## All writes use the same path

Every command goes through one processor.

The Station authenticates the caller, checks for an existing receipt, authorizes the command, loads the required state, checks aggregate versions, and calls `sv-core`.

When the command succeeds, the Station stores the state changes, journal events, effects, projections, and receipt in one SQLite transaction.

This matters during retries.

The client creates a command ID when the operator performs an action. If the connection drops after SQLite commits, the client can send the same command again. The Station returns the existing receipt instead of processing the payment twice.

Using the same command ID with different content is rejected.

Deterministic business rejections also receive receipts. Temporary failures do not, because retrying them may produce a different result.

## Offline commands

The browser stores offline commands in IndexedDB. It does not store patches to business state and does not run another copy of the transaction core.

When the Station becomes available, the browser sends the original command with its original ID.

This limits what the application can do while disconnected, but it avoids having two systems independently approve different versions of the same sale.

## External work

Printing, fiscal submission, payment-provider calls, and relay work happen after the database commit.

The transaction records each required operation as an effect in an outbox. Workers process those effects later and report the result through another command.

This does not make printers or providers exactly-once systems. It makes the Station’s intent durable and each attempt traceable.

## Evidence

The repository contains twelve domain laws written in Brazilian Portuguese. They cover bill conservation, split payments, cash custody, settlements, cashback, printing, and fiscal evidence.

The laws are linked to tests. A replay corpus also checks that the core produces the same decisions byte for byte.

Money uses integer cents. The browser can request provisional prices through a WebAssembly interface backed by the same Rust rules. If the rule versions differ, pricing is disabled instead of falling back to a JavaScript implementation.

Receipts and journal events are immutable. Corrections create new records instead of rewriting earlier evidence.

## Where it stands

v1 is live. The core, the Station, and the application shell are audited, tested, and running real service: my own bar and café. Outside sales start on 10 August 2026.

Clean-machine installation, printer operations, backup and restore procedures, provider custody, and hardware behaviour have now been exercised on sites rather than in a development environment.

Fiscal submission is the one part still closing. The command path and the outbox record every attempt, but the certification work is not finished.

Agnaldo Guerra · Southern Brazil · 2026

---

## Other pages

- [Home](https://agnaldoguerra.com/index.md)
- [Mixology notes](https://agnaldoguerra.com/mixology/index.md)
