feat: complete inventory image and sales workflows
Quality / test (push) Canceled after 0s

Commit the working vertical slices for inventory image processing and the Sale workflow, including Sale history, audited voiding, multi-item persistence, admin UI, migrations, documentation, and tests.
This commit is contained in:
2026-09-09 00:35:57 -04:00
parent ea145191df
commit 8e5ce80196
32 changed files with 1092 additions and 226 deletions
+11 -3
View File
@@ -73,7 +73,15 @@ Integration tests reject database names not ending in `_test` and truncate their
## Local Development
After creating `.env` and setting the required local SMTP and MFA values, start the complete development stack from the repository root with:
After creating `.env`, set the required local SMTP and MFA values, then start the complete development stack from the repository root with:
```env
SMTP_URL=smtp://localhost:1025
SMTP_FROM=no-reply@example.test
MFA_ENCRYPTION_KEY=<output from: openssl rand -base64 32>
```
The MFA key must remain stable while enrolled MFA methods exist. Keep it in local secret storage and do not commit it.
```sh
npm run dev
@@ -132,8 +140,8 @@ After the development database is migrated, set `INITIAL_ADMIN_EMAIL`, `INITIAL_
## Password Recovery
Set `SMTP_URL`, `SMTP_FROM`, and `PASSWORD_RESET_URL` in the local `.env` before starting the API. Password reset tokens are delivered only through SMTP, expire after one hour, are stored as hashes, and are single use.
Set `SMTP_URL`, `SMTP_FROM`, and `PASSWORD_RESET_URL` in the local `.env` before starting the API. For local development with an SMTP service listening on port `1025`, use `SMTP_URL=smtp://localhost:1025` and `SMTP_FROM=no-reply@example.test`. Password reset tokens are delivered only through SMTP, expire after one hour, are stored as hashes, and are single use.
## MFA Secret Protection
Set `MFA_ENCRYPTION_KEY` to a base64-encoded 32-byte key before starting the API. Generate one with `openssl rand -base64 32`; keep it in secret management and retain it for as long as enrolled MFA methods must remain readable.
Set `MFA_ENCRYPTION_KEY` to a base64-encoded 32-byte key before starting the API. Generate one with `openssl rand -base64 32`, then paste the output after `MFA_ENCRYPTION_KEY=` in `.env`. A command that only runs `printf` displays the value but does not update `.env`. Keep the key in secret management and retain it for as long as enrolled MFA methods must remain readable.