Reference server
The reference server in backend/ implements version 1 with Laravel. Its own README covers installation; this page lists what affects protocol behaviour.
Configuration
Section titled “Configuration”| Variable | Default | Effect on the protocol |
|---|---|---|
LVE_SERVER_NAME |
APP_NAME, else LVE |
info.server.name |
LVE_LICENSE |
empty | info.license; left out when empty |
LVE_INVENTORY_ID |
derived from APP_KEY |
inventory.id at sign-in. Set once, never change. |
LVE_INVENTORY_NAME |
APP_NAME, else LVE |
inventory.name at sign-in |
LVE_DELIVERY_NOTE_FORMAT |
LS-{YYYY}-{SEQ:5} |
Format of reserved delivery note numbers |
LVE_TIMEZONE |
Europe/Berlin (INVENTAR_TIMEZONE is read as fallback) |
Calendar year of reserved numbers |
APP_KEY |
Keys the pairing code hashes; the fallback inventory id is derived from it | |
APP_URL |
Default base URL in pairing links |
Fixed limits
Section titled “Fixed limits”| Limit | Value |
|---|---|
| Changes per push | 500 |
| Pull page size | default 500, at most 1000 |
| Numbers per reservation | 1 to 100 |
| Attachment size | 20 MiB |
| Sign-in rate | 10 per minute per client address, shared by both sign-in endpoints |
| Pairing code lifetime | 24 hours unless --hours is given |
The web server in front of PHP must accept request bodies of 20 MiB (client_max_body_size in nginx).
Console commands
Section titled “Console commands”| Command | Purpose |
|---|---|
php artisan lve:user {name} {username} [--email=] [--password=] |
Create a user. Username lower case, without spaces or @; password at least 8 characters (asked for when left out). Users sign in with the username or the email address. |
php artisan lve:pair {user} [--hours=24] [--server=] |
Create a single-use pairing code for a user (id, username or email). Prints the code, its expiry, the link lve://pair?server=...&code=... and a QR code in the terminal, and writes the QR code as PNG to storage/app/private/pairing/. --server overrides APP_URL as the base URL in the link. |
php artisan lve:loan-terms [--employee=FILE] [--external=FILE] [--jurisdiction=de|at|ch|intl] [--lock|--unlock] |
Set the loan conditions for all devices: reads the conditions from text files (an empty file returns to the app's standard text), sets the jurisdiction and locks or unlocks the loan template. Writes the template 00000000-0000-4000-8000-000000000003 as a server-side change; fields it does not touch are kept. |
php artisan lve:project [--fresh] |
Rebuild the read model for other systems from the record store |
Console output is in the application locale (de or en).
Behaviour details
Section titled “Behaviour details”- Every endpoint below
/lveanswers errors in the protocol format, localised byAccept-Language(German by default), and setsContent-Language. - A JSON body that does not parse is answered with
400 malformed_requestbefore validation. - Pushed changes are decoded with objects kept as objects, so
{}in a payload stays{}. - Each pushed change is stored in its own transaction under one row lock on the change log; a projection failure is logged and does not fail the push.
sync_recordsandsync_changeshold ids and stamps in upper case; payloads are stored as JSON text re-encoded with unescaped Unicode and slashes and with1.0kept apart from1.- Attachments are streamed to a temporary file while hashing, so a 20 MiB upload never sits in memory.
/upanswers a health check outside the protocol.