Skip to content

Conformance checklist

Use these lists to review an implementation. Each item links to the page with the full rule. Items marked SHOULD are recommended but not needed for interoperability.

  • GET /lve/v1/info answers without authentication with protocol: "lve-sync", versions containing 1, server, auth, features, and license only when a licence is configured. Discovery
  • POST /lve/v1/auth/token and/or POST /lve/v1/auth/pair issue a bearer token bound to device.id and answer token, user.id (string), user.name, inventory.id, inventory.name. Authentication
  • Signing in again with the same user and device id replaces the previous token.
  • Pairing codes work once, expire, and are compared without case, spaces and dashes. Two concurrent redemptions of one code cannot both succeed.
  • Sign-in endpoints are rate-limited and answer 429 with too_many_requests.
  • DELETE /lve/v1/auth/token revokes only the token of the request and answers 204.
  • Every authenticated endpoint answers 401 with unauthenticated for a missing or revoked token.
  • inventory.id never changes while devices are connected.
  • Accepts up to 500 changes; refuses more with 422 too_many_changes without storing anything. Push
  • Answers exactly one result per change at the same index, echoing id and entity as sent.
  • Rejects malformed envelopes with invalid_change, deletes of movements with immutable, invalid payloads of known types with invalid_payload, changes to locked templates with locked.
  • Never rejects a change because of stock, references or duplicate numbers.
  • Applies mutable records only when the stamp is greater than the stored one (byte-wise, upper case), tombstones included; answers ignored otherwise. Merge rules
  • Applies a movement only when its id is new; answers ignored otherwise.
  • Stores and relays unknown entity types and unknown fields unchanged; keeps {} as an object.
  • Compares ids case-insensitively.
  • Stores each change atomically; a failure does not leave a change half stored, and a rejected change does not affect the others.
  • Serialises the merge decision per record, so concurrent pushes of one record cannot both apply out of order.
  • Without cursor returns the current version of every record, tombstones included, paged, ending with a cursor that covers every change applied since the first page. Pull
  • With cursor returns every applied change after it, in application order, including the caller's own.
  • Never lets a reader see a later log position before an earlier one is committed.
  • Honours limit (1 to 1000, default 500) and sets has_more exactly when changes were held back.
  • Always returns a cursor, also on an empty page.
  • Answers a cursor it did not issue with 400 invalid_cursor.
  • PUT verifies the SHA-256 of the body against the path (422 hash_mismatch), limits the size to 20 MiB (413 payload_too_large), answers 201 when stored and 200 when already present. Attachments
  • HEAD answers 200 or 404; GET returns the bytes with the stored content type.
  • Keeps every attachment that a current record version references.
  • If number_ranges is announced: hands out every number once across all devices, consecutive within a response, restarting each calendar year in the business time zone. Number ranges
  • Answers errors as {"error": {"code", "message"}} with the codes of Errors, localised by Accept-Language (de, en) and named in Content-Language.
  • Uses HTTPS when reachable from the internet. Security
  • Writes its own changes (administration, migrations, ERP imports) as new versions with greater stamps, node 00000000, appended to the log. Server-side writes
  • SHOULD keep tombstones and the change log forever, or answer cursors into a compacted range with invalid_cursor.
  • Keeps a full local copy of the inventory and works without a connection. Records
  • Writes ids in upper case, compares them case-insensitively, uses fresh random UUIDs for new records and the fixed ids for the company profile and the two templates.
  • Stamps every local write with a hybrid logical clock: 15-digit milliseconds, 4-digit upper-case hex counter, 8-digit upper-case hex node; strictly greater than every stamp issued or observed.
  • Observes every received stamp before merging it.
  • Merges received changes with the merge rules: greater stamp wins for mutable records, first write wins for movements.
  • Never changes or deletes a movement; corrects with counter-bookings.
  • Writes whole records; keeps unknown top-level fields of the previous version when writing a new one; sends null to clear a field.
  • Stores and relays unknown entity types.
  • Reads payloads leniently: applies documented defaults for missing optional fields; ignores unknown fields and unknown values of open lists.
  • Writes strict JSON types: numbers, booleans, RFC 3339 timestamps with seconds and time zone, lowercase SHA-256 hashes.
  • Checks protocol and versions before signing in; verifies the licence if one is sent. Discovery, Licence
  • Stores the token in secure storage; on 401 stops syncing, keeps local data and asks the user to sign in again.
  • After signing in, drops any old cursor and queues every local record for push.
  • Keeps an outbox of local changes in write order; pushes it oldest first in batches of at most 500.
  • Uploads every attachment a batch references (that it holds) before pushing the batch.
  • Removes applied and ignored entries; keeps rejected entries with their message and lets the user retry or discard them.
  • Pulls until has_more is false, merges each page before persisting its cursor, and starts over on invalid_cursor.
  • Downloads missing attachments and verifies their SHA-256.
  • Treats 5xx, 429 and transport errors as temporary and retries later; waits for Retry-After.
  • Sends Accept-Language; decides by error codes, never by messages.
  • Uses HTTPS except in a trusted local network.
  • Derives stock, serial states, low stock and loan state with the rules of Derived state; never stores them as records.
  • Writes one issue movement per delivery note line with delivery_note_id, and the note with movement_id per item, copies of recipient and article data, signatures and PDF. Delivery notes
  • Writes one issue movement per loan item at handover and one receipt per returned line with loan_id; writes returns only with both signatures; writes no movement for lost units. Loans
  • Freezes terms and penalty in the loan at handover.
  • Numbers documents with device numbering or reserved server numbers; never assumes numbers are unique across devices. Number ranges
  • Shows locked templates read-only and does not write them.
  • SHOULD apply the device booking checks (stock, serial numbers) before writing movements.
  • SHOULD warn before merging local data into a server whose inventory id differs from the previous connection.