{
  "schema_version": 1,
  "diagram_type": "sequence",
  "meta": {
    "title": "iSpeed.my — Authentication & MFA Flow",
    "subtitle": "Login, session creation, and device-based MFA challenge",
    "output": "ispeed-authentication.html",
    "viewBox": [1080, 650],
    "column_fit": "spread",
    "animation": "trace",
    "quality_profile": "showcase",
    "views": [
      { "id": "login", "label": "Login", "focus": ["user", "app", "mobile-api", "vbroker", "session"], "note": "Credential validation and session creation" },
      { "id": "mfa", "label": "MFA Challenge", "focus": ["app", "mobile-api", "mfa", "fcm"], "note": "Device-based push challenge" },
      { "id": "full-flow", "label": "Full Flow", "focus": ["user", "app", "mobile-api", "session", "mfa", "vbroker", "fcm"], "note": "Complete authentication lifecycle" }
    ]
  },
  "participants": [
    { "id": "user", "type": "external", "label": "User", "sublabel": "Trader" },
    { "id": "app", "type": "frontend", "label": "React Native App", "sublabel": "Expo SDK 56" },
    { "id": "mobile-api", "type": "backend", "label": "Mobile API", "sublabel": "rt-mx-mobile-api" },
    { "id": "session", "type": "database", "label": "AuthConn", "sublabel": "USER_SESSION" },
    { "id": "mfa", "type": "database", "label": "MFA DB", "sublabel": "mfa_devices_users" },
    { "id": "vbroker", "type": "backend", "label": "VBroker API", "sublabel": "/vbroker login" },
    { "id": "fcm", "type": "cloud", "label": "FCM Push", "sublabel": "Firebase" }
  ],
  "segments": [
    { "from": 150, "to": 382, "label": "Login" },
    { "from": 388, "to": 600, "label": "MFA Challenge" }
  ],
  "messages": [
    { "id": "a1", "from": "user", "to": "app", "y": 160, "label": "Open login", "variant": "default" },
    { "id": "a2", "from": "app", "to": "mobile-api", "y": 190, "label": "POST /member login (90019)", "variant": "emphasis" },
    { "id": "a3", "from": "mobile-api", "to": "vbroker", "y": 220, "label": "vbAPI.login", "variant": "default" },
    { "id": "a4", "from": "vbroker", "to": "session", "y": 250, "label": "validate credentials", "variant": "security" },
    { "id": "a5", "from": "vbroker", "to": "mobile-api", "y": 280, "label": "login result", "variant": "return" },
    { "id": "a6", "from": "mobile-api", "to": "session", "y": 310, "label": "store USER_SESSION", "variant": "security" },
    { "id": "a7", "from": "mobile-api", "to": "app", "y": 340, "label": "bV_SessionID + flags", "variant": "return" },
    { "id": "a8", "from": "app", "to": "user", "y": 370, "label": "Logged in", "variant": "return" },
    { "id": "a9", "from": "app", "to": "mobile-api", "y": 400, "label": "MFA challenge (90040)", "variant": "emphasis" },
    { "id": "a10", "from": "mobile-api", "to": "mfa", "y": 430, "label": "create challenge", "variant": "default" },
    { "id": "a11", "from": "mobile-api", "to": "fcm", "y": 460, "label": "send push", "variant": "dashed" },
    { "id": "a12", "from": "mfa", "to": "mobile-api", "y": 490, "label": "device approved (WebSocket)", "variant": "return" },
    { "id": "a13", "from": "mobile-api", "to": "app", "y": 520, "label": "MFA0124 + session", "variant": "return" },
    { "id": "a14", "from": "app", "to": "user", "y": 550, "label": "Session ready", "variant": "return" }
  ],
  "activations": [
    { "participant": "app", "from": 155, "to": 560, "type": "frontend" },
    { "participant": "mobile-api", "from": 185, "to": 535, "type": "backend" },
    { "participant": "vbroker", "from": 215, "to": 285, "type": "backend" },
    { "participant": "session", "from": 245, "to": 320, "type": "database" },
    { "participant": "mfa", "from": 425, "to": 495, "type": "database" },
    { "participant": "fcm", "from": 455, "to": 465, "type": "cloud" }
  ],
  "cards": [
    {
      "dot": "emerald",
      "title": "Session Store",
      "items": [
        "Sessions live in USER_SESSION (authorisation DB)",
        "Mobile sessions keyed by bV_SessionID",
        "Web sessions use a JSESSIONID cookie"
      ]
    },
    {
      "dot": "violet",
      "title": "Single Session",
      "items": [
        "SessionTerminationService keeps one session per platform",
        "Build values: android-phone, iphone, web-pc",
        "MFA approval terminates other mobile sessions"
      ]
    },
    {
      "dot": "rose",
      "title": "MFA Security",
      "items": [
        "Device-bound OTP and WebSocket challenge",
        "FCM channel ispeed.rakuten.my.fcm.alert.ANDROID_MFA",
        "Challenge timeout defaults to 40 seconds"
      ]
    }
  ]
}
