Event Model

evergreenLast update on Sep 1, 2026
Download .md

Event Model

Asset facts should be append-only. State changes are represented by new events, not edits.

Principles

  • Every user-confirmed action creates an event.
  • Events are immutable after creation.
  • Corrections and tag replacements are new events.
  • Events carry client-minted IDs so retries are safe.
  • Backend ingest must deduplicate by event ID.

Target Sync Contract

POST /api/v1/events/sync
Content-Type: application/json
Authorization: Bearer <token>
{
  "events": [
    {
      "event_id": "018f4b7e-...",
      "event_type": "ASSET_ONBOARDED",
      "asset_code": "AST-0001",
      "origin": "mobile",
      "actor": "user-id",
      "occurred_at": "2026-09-01T05:30:00Z",
      "payload": {}
    }
  ]
}

Expected response:

{
  "received": 12,
  "inserted": 10,
  "duplicates": 2
}

Backend Ingest Rule

INSERT INTO asset_event (...)
VALUES (...)
ON CONFLICT (event_id) DO NOTHING;

POC Event Types

EventMeaning
DELIVERY_RECEIVEDDelivery accepted
DELIVERY_REJECTEDDelivery rejected
ASSET_ONBOARDEDUnit committed to inventory
GAN_ATTACHEDGoods acceptance note captured
GAN_DEFERREDGoods acceptance note missing at commit
ASSET_CORRECTEDPost-submit field correction
TAG_REPLACEDTemporary or missing tag replaced
ASSET_RECEIVELegacy receive event
ASSIGN_CONFIRMLegacy assignment confirmation

Queue Behavior

flowchart TD
    A["User confirms action"] --> B["Create immutable event"]
    B --> C["Insert into local queue"]
    C --> D{"Network available?"}
    D -- No --> E["Remain pending"]
    D -- Yes --> F["POST unsynced batch"]
    F --> G{"Backend accepts?"}
    G -- Yes --> H["Mark events synced"]
    G -- No --> E

Current POC Details

  • Queue database: asset_event_queue.db.
  • Queue table: asset_event_queue.
  • Local database version: 2.
  • Current migration renames payload key value to unit_price.
  • Backend URL is hard-coded in reference/mobile_app_demo/lib/services/sync_service.dart.