{
  "ranAt": "2026-08-19T03:07:56.121Z",
  "wp": "WP-SMOKE-IDEMPOTENCY-01",
  "summary": {
    "total": 56,
    "pass": 35,
    "fail": 21,
    "avgCompleteness": 62.1
  },
  "gaps": [
    {
      "step": "auth.verify.consumer",
      "wp": "AUTH",
      "missing": [
        "accessToken",
        "refreshToken",
        "tokenType",
        "expiresInSec",
        "user.id",
        "user.phone",
        "user.roles",
        "surface",
        "driver.hasRole",
        "driver.applicationStatus",
        "driver.requiresRegistration",
        "partner.hasRole",
        "partner.applicationStatus",
        "partner.requiresRegistration"
      ],
      "completeness": 0,
      "http": 403,
      "status": "FAIL",
      "errorCode": "ACCOUNT_IS_DRIVER",
      "businessReason": "Tài khoản tài xế không dùng app khách hàng. Hãy mở WELIFE Driver."
    },
    {
      "step": "users.me",
      "wp": "USER",
      "missing": [
        "id",
        "phone",
        "roles",
        "fullName",
        "email",
        "gender",
        "birthDate",
        "avatarUrl",
        "points",
        "createdAt"
      ],
      "completeness": 0,
      "http": 401,
      "status": "FAIL",
      "errorCode": "UNAUTHORIZED",
      "businessReason": "Unauthorized"
    },
    {
      "step": "medical.vax.book",
      "wp": "MED",
      "missing": [
        "id",
        "facilityId",
        "scheduledAt",
        "status",
        "reason",
        "amount",
        "kind",
        "code",
        "facility.name"
      ],
      "completeness": 0,
      "http": 401,
      "status": "FAIL",
      "errorCode": "UNAUTHORIZED",
      "businessReason": "Unauthorized"
    },
    {
      "step": "medical.health.history",
      "wp": "MED",
      "missing": [
        "items",
        "count",
        "items[].id",
        "items[].title",
        "items[].kind",
        "items[].status",
        "items[].at",
        "items[].facility"
      ],
      "completeness": 0,
      "http": 401,
      "status": "FAIL",
      "errorCode": "UNAUTHORIZED",
      "businessReason": "Unauthorized"
    },
    {
      "step": "media.upload",
      "wp": "MEDIA",
      "missing": [
        "id",
        "objectKey",
        "publicUrl",
        "mimeType",
        "sizeBytes",
        "originalName",
        "kind",
        "status",
        "createdAt"
      ],
      "completeness": 0,
      "http": 401,
      "status": "FAIL",
      "errorCode": "UNAUTHORIZED",
      "businessReason": "Unauthorized"
    },
    {
      "step": "addr.create",
      "wp": "ADDR",
      "missing": [
        "id",
        "label",
        "recipientName",
        "phone",
        "line1",
        "line2",
        "ward",
        "district",
        "city",
        "country",
        "lat",
        "lng",
        "isDefault",
        "createdAt",
        "updatedAt"
      ],
      "completeness": 0,
      "http": 401,
      "status": "FAIL",
      "errorCode": "UNAUTHORIZED",
      "businessReason": "Unauthorized"
    },
    {
      "step": "addr.default",
      "wp": "ADDR",
      "missing": [
        "id",
        "label",
        "line1",
        "city",
        "lat",
        "lng",
        "isDefault",
        "country"
      ],
      "completeness": 0,
      "http": 401,
      "status": "FAIL",
      "errorCode": "UNAUTHORIZED",
      "businessReason": "Unauthorized"
    },
    {
      "step": "wallet.topup",
      "wp": "WALLET",
      "missing": [
        "id",
        "type",
        "amount",
        "balanceAfter",
        "reason",
        "note",
        "idempotencyKey",
        "createdAt",
        "balance",
        "replayed"
      ],
      "completeness": 0,
      "http": 401,
      "status": "FAIL",
      "errorCode": "UNAUTHORIZED",
      "businessReason": "Unauthorized"
    },
    {
      "step": "wallet.topup.idem",
      "wp": "WALLET",
      "missing": [
        "balance",
        "replayed",
        "id"
      ],
      "completeness": 0,
      "http": 401,
      "status": "FAIL",
      "errorCode": "UNAUTHORIZED",
      "businessReason": "Unauthorized"
    },
    {
      "step": "wallet.balance",
      "wp": "WALLET",
      "missing": [
        "accountId",
        "currency",
        "balance",
        "updatedAt"
      ],
      "completeness": 0,
      "http": 401,
      "status": "FAIL",
      "errorCode": "UNAUTHORIZED",
      "businessReason": "Unauthorized"
    },
    {
      "step": "wallet.tx",
      "wp": "WALLET",
      "missing": [
        "items",
        "count",
        "balance",
        "items[].id",
        "items[].type",
        "items[].amount",
        "items[].balanceAfter",
        "items[].createdAt"
      ],
      "completeness": 0,
      "http": 401,
      "status": "FAIL",
      "errorCode": "UNAUTHORIZED",
      "businessReason": "Unauthorized"
    },
    {
      "step": "fnb.cart.add",
      "wp": "FNB",
      "missing": [
        "id",
        "merchantId",
        "items",
        "subtotal",
        "items[].menuItemId",
        "items[].name",
        "items[].price",
        "items[].quantity",
        "items[].lineTotal"
      ],
      "completeness": 0,
      "http": 401,
      "status": "FAIL",
      "errorCode": "UNAUTHORIZED",
      "businessReason": "Unauthorized"
    },
    {
      "step": "fnb.order",
      "wp": "FNB",
      "missing": [
        "id",
        "status",
        "subtotal",
        "discount",
        "total",
        "note",
        "addressSnapshot",
        "addressSnapshot.label",
        "addressSnapshot.line1",
        "addressSnapshot.city",
        "addressSnapshot.lat",
        "addressSnapshot.lng",
        "merchant.id",
        "merchant.name",
        "merchant.slug",
        "items",
        "items[].id",
        "items[].name",
        "items[].unitPrice",
        "items[].quantity",
        "items[].lineTotal",
        "createdAt",
        "updatedAt"
      ],
      "completeness": 0,
      "http": 401,
      "status": "FAIL",
      "errorCode": "UNAUTHORIZED",
      "businessReason": "Unauthorized"
    },
    {
      "step": "ride.quote",
      "wp": "RIDE",
      "missing": [
        "id",
        "distanceMeters",
        "durationSec",
        "fareAmount",
        "currency",
        "expiresAt",
        "options",
        "options[].vehicle",
        "options[].fareAmount"
      ],
      "completeness": 0,
      "http": 401,
      "status": "FAIL",
      "errorCode": "UNAUTHORIZED",
      "businessReason": "Unauthorized"
    },
    {
      "step": "ride.create",
      "wp": "RIDE",
      "missing": [
        "id",
        "quoteId",
        "status",
        "pickupLat",
        "pickupLng",
        "dropoffLat",
        "dropoffLng",
        "distanceMeters",
        "durationSec",
        "fareAmount",
        "currency",
        "cancelReason",
        "createdAt",
        "updatedAt",
        "driverId"
      ],
      "completeness": 0,
      "http": 401,
      "status": "FAIL",
      "errorCode": "UNAUTHORIZED",
      "businessReason": "Unauthorized"
    },
    {
      "step": "ride.cancel",
      "wp": "RIDE",
      "missing": [
        "id",
        "status",
        "cancelReason"
      ],
      "completeness": 0,
      "http": 401,
      "status": "FAIL",
      "errorCode": "UNAUTHORIZED",
      "businessReason": "Unauthorized"
    },
    {
      "step": "driver.register",
      "wp": "DRV",
      "missing": [],
      "completeness": 100,
      "http": 409,
      "status": "PASS",
      "errorCode": "DRIVER_ALREADY_REGISTERED",
      "businessReason": "Đã có hồ sơ tài xế (APPROVED)"
    },
    {
      "step": "driver.accept",
      "wp": "DRV",
      "missing": [
        "id",
        "status"
      ],
      "completeness": 0,
      "http": 400,
      "status": "FAIL",
      "errorCode": null,
      "businessReason": "Chuyến không còn available"
    },
    {
      "step": "driver.pickup",
      "wp": "DRV",
      "missing": [
        "id",
        "status"
      ],
      "completeness": 0,
      "http": 403,
      "status": "FAIL",
      "errorCode": null,
      "businessReason": "Không phải chuyến của bạn"
    },
    {
      "step": "driver.complete",
      "wp": "DRV",
      "missing": [
        "id",
        "status"
      ],
      "completeness": 0,
      "http": 403,
      "status": "FAIL",
      "errorCode": null,
      "businessReason": "Không phải chuyến của bạn"
    },
    {
      "step": "driver.earnings",
      "wp": "DRV",
      "missing": [
        "message"
      ],
      "completeness": 75,
      "http": 200,
      "status": "PASS",
      "errorCode": null,
      "businessReason": null
    },
    {
      "step": "partner.onboarding",
      "wp": "PAR",
      "missing": [],
      "completeness": 100,
      "http": 409,
      "status": "PASS",
      "errorCode": "PARTNER_ALREADY_REGISTERED",
      "businessReason": "Đã có hồ sơ partner (APPROVED)"
    }
  ],
  "steps": [
    {
      "step": "health",
      "wp": "INFRA",
      "method": "GET",
      "path": "/health",
      "http": 200,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 4,
      "fields": [
        "status",
        "service",
        "env",
        "timestamp"
      ],
      "missing": [],
      "sample": {
        "status": "ok",
        "service": "welife-api",
        "env": "development",
        "timestamp": "2026-08-19T03:07:54.274Z"
      },
      "note": "",
      "errorCode": null,
      "businessReason": null,
      "error": null
    },
    {
      "step": "health.deps",
      "wp": "INFRA",
      "method": "GET",
      "path": "/health/deps",
      "http": 200,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 9,
      "fields": [
        "status",
        "deps",
        "deps.postgres",
        "deps.redis",
        "deps.minio",
        "ports",
        "ports.postgres",
        "ports.redis",
        "ports.minio"
      ],
      "missing": [],
      "sample": {
        "status": "ok",
        "deps": "object",
        "ports": "object"
      },
      "note": "",
      "errorCode": null,
      "businessReason": null,
      "error": null
    },
    {
      "step": "auth.otp.send",
      "wp": "AUTH",
      "method": "POST",
      "path": "/auth/otp/send",
      "http": 200,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 8,
      "fields": [
        "success",
        "message",
        "expiresInSec",
        "surface",
        "otpBackend",
        "smsProvider",
        "smsSent",
        "devOtp"
      ],
      "missing": [],
      "sample": {
        "success": "true",
        "message": "Đã tạo OTP (SMS …len=47",
        "expiresInSec": "300",
        "surface": "CONSUMER",
        "otpBackend": "redis",
        "smsProvider": "console",
        "smsSent": "true",
        "devOtp": "141795"
      },
      "note": "",
      "errorCode": null,
      "businessReason": null,
      "error": null
    },
    {
      "step": "auth.verify.consumer",
      "wp": "AUTH",
      "method": "POST",
      "path": "/auth/otp/verify",
      "http": 403,
      "status": "FAIL",
      "completeness": 0,
      "fieldCount": 6,
      "fields": [
        "statusCode",
        "code",
        "error",
        "message",
        "path",
        "timestamp"
      ],
      "missing": [
        "accessToken",
        "refreshToken",
        "tokenType",
        "expiresInSec",
        "user.id",
        "user.phone",
        "user.roles",
        "surface",
        "driver.hasRole",
        "driver.applicationStatus",
        "driver.requiresRegistration",
        "partner.hasRole",
        "partner.applicationStatus",
        "partner.requiresRegistration"
      ],
      "sample": {
        "statusCode": "403",
        "code": "ACCOUNT_IS_DRIVER",
        "error": "FORBIDDEN",
        "message": "Tài khoản tài xế…len=65",
        "path": "/api/v1/auth/otp/verify",
        "timestamp": "2026-08-19T03:07:54.328Z"
      },
      "note": "",
      "errorCode": "ACCOUNT_IS_DRIVER",
      "businessReason": "Tài khoản tài xế không dùng app khách hàng. Hãy mở WELIFE Driver.",
      "error": "Tài khoản tài xế không dùng app khách hàng. Hãy mở WELIFE Driver."
    },
    {
      "step": "users.me",
      "wp": "USER",
      "method": "GET",
      "path": "/users/me",
      "http": 401,
      "status": "FAIL",
      "completeness": 0,
      "fieldCount": 5,
      "fields": [
        "statusCode",
        "error",
        "message",
        "path",
        "timestamp"
      ],
      "missing": [
        "id",
        "phone",
        "roles",
        "fullName",
        "email",
        "gender",
        "birthDate",
        "avatarUrl",
        "points",
        "createdAt"
      ],
      "sample": {
        "statusCode": "401",
        "error": "UNAUTHORIZED",
        "message": "Unauthorized",
        "path": "/api/v1/users/me",
        "timestamp": "2026-08-19T03:07:54.336Z"
      },
      "note": "",
      "errorCode": "UNAUTHORIZED",
      "businessReason": "Unauthorized",
      "error": "Unauthorized"
    },
    {
      "step": "medical.vax.list",
      "wp": "MED",
      "method": "GET",
      "path": "/medical/health/vax-suggestions",
      "http": 200,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 11,
      "fields": [
        "items",
        "items[].id",
        "items[].name",
        "items[].facility",
        "items[].facilityId",
        "items[].phone",
        "items[].estimatedAt",
        "items[].note",
        "items[].status",
        "items[].appointmentId",
        "count"
      ],
      "missing": [],
      "sample": {
        "items": "array[3]",
        "count": "3"
      },
      "note": "",
      "errorCode": null,
      "businessReason": null,
      "error": null
    },
    {
      "step": "medical.vax.detail",
      "wp": "MED",
      "method": "GET",
      "path": "/medical/health/vax-suggestions/:id",
      "http": 200,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 9,
      "fields": [
        "id",
        "name",
        "facility",
        "facilityId",
        "phone",
        "estimatedAt",
        "note",
        "status",
        "appointmentId"
      ],
      "missing": [],
      "sample": {
        "id": "vax-hpv",
        "name": "Tiêm phòng HPV",
        "facility": "Trung tâm Tiêm chủng VNVC Quận 7",
        "facilityId": "863356a7-eef3-49e8-9fa0-cdfdedebac60",
        "phone": "+842873000888",
        "estimatedAt": "2026-09-02T03:07:54.370Z",
        "note": "Liều nhắc theo phác đồ. Mang CMND/CCCD.",
        "status": "SUGGESTED",
        "appointmentId": "null"
      },
      "note": "",
      "errorCode": null,
      "businessReason": null,
      "error": null
    },
    {
      "step": "medical.vax.book",
      "wp": "MED",
      "method": "POST",
      "path": "/medical/health/vax-bookings",
      "http": 401,
      "status": "FAIL",
      "completeness": 0,
      "fieldCount": 5,
      "fields": [
        "statusCode",
        "error",
        "message",
        "path",
        "timestamp"
      ],
      "missing": [
        "id",
        "facilityId",
        "scheduledAt",
        "status",
        "reason",
        "amount",
        "kind",
        "code",
        "facility.name"
      ],
      "sample": {
        "statusCode": "401",
        "error": "UNAUTHORIZED",
        "message": "Unauthorized",
        "path": "/api/v1/medical/health/vax-bookings",
        "timestamp": "2026-08-19T03:07:54.384Z"
      },
      "note": "already booked ok",
      "errorCode": "UNAUTHORIZED",
      "businessReason": "Unauthorized",
      "error": "Unauthorized"
    },
    {
      "step": "medical.health.history",
      "wp": "MED",
      "method": "GET",
      "path": "/medical/health/history",
      "http": 401,
      "status": "FAIL",
      "completeness": 0,
      "fieldCount": 5,
      "fields": [
        "statusCode",
        "error",
        "message",
        "path",
        "timestamp"
      ],
      "missing": [
        "items",
        "count",
        "items[].id",
        "items[].title",
        "items[].kind",
        "items[].status",
        "items[].at",
        "items[].facility"
      ],
      "sample": {
        "statusCode": "401",
        "error": "UNAUTHORIZED",
        "message": "Unauthorized",
        "path": "/api/v1/medical/health/history?kind=ALL",
        "timestamp": "2026-08-19T03:07:54.398Z"
      },
      "note": "",
      "errorCode": "UNAUTHORIZED",
      "businessReason": "Unauthorized",
      "error": "Unauthorized"
    },
    {
      "step": "places.nearby",
      "wp": "PLACE",
      "method": "GET",
      "path": "/places/nearby",
      "http": 200,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 15,
      "fields": [
        "items",
        "items[].id",
        "items[].name",
        "items[].type",
        "items[].address",
        "items[].district",
        "items[].lat",
        "items[].lng",
        "items[].rating",
        "items[].reviewCount",
        "items[].imageUrl",
        "items[].tags",
        "items[].openNow",
        "items[].distanceM",
        "count"
      ],
      "missing": [],
      "sample": {
        "items": "array[16]",
        "count": "16"
      },
      "note": "",
      "errorCode": null,
      "businessReason": null,
      "error": null
    },
    {
      "step": "atm.nearby",
      "wp": "ATM",
      "method": "GET",
      "path": "/atms/nearby",
      "http": 200,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 13,
      "fields": [
        "items",
        "items[].id",
        "items[].name",
        "items[].bank",
        "items[].address",
        "items[].lat",
        "items[].lng",
        "items[].feeNote",
        "items[].open24h",
        "items[].hasCash",
        "items[].imageUrl",
        "items[].distanceM",
        "count"
      ],
      "missing": [],
      "sample": {
        "items": "array[88]",
        "count": "88"
      },
      "note": "",
      "errorCode": null,
      "businessReason": null,
      "error": null
    },
    {
      "step": "atm.banks",
      "wp": "ATM",
      "method": "GET",
      "path": "/atms/banks",
      "http": 200,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 3,
      "fields": [
        "items",
        "items[].name",
        "count"
      ],
      "missing": [],
      "sample": {
        "items": "array[24]",
        "count": "24"
      },
      "note": "",
      "errorCode": null,
      "businessReason": null,
      "error": null
    },
    {
      "step": "fuel.nearby",
      "wp": "FUEL",
      "method": "GET",
      "path": "/fuel/stations/nearby",
      "http": 200,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 18,
      "fields": [
        "items",
        "items[].id",
        "items[].brand",
        "items[].name",
        "items[].address",
        "items[].lat",
        "items[].lng",
        "items[].openNow",
        "items[].inventoryLiters",
        "items[].partnerOrgId",
        "items[].imageUrl",
        "items[].prices",
        "items[].prices.ron95",
        "items[].prices.e5",
        "items[].prices.diesel",
        "items[].pricesUpdatedAt",
        "items[].distanceM",
        "count"
      ],
      "missing": [],
      "sample": {
        "items": "array[64]",
        "count": "64"
      },
      "note": "",
      "errorCode": null,
      "businessReason": null,
      "error": null
    },
    {
      "step": "fuel.brands",
      "wp": "FUEL",
      "method": "GET",
      "path": "/fuel/brands",
      "http": 200,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 3,
      "fields": [
        "items",
        "items[].name",
        "count"
      ],
      "missing": [],
      "sample": {
        "items": "array[46]",
        "count": "46"
      },
      "note": "",
      "errorCode": null,
      "businessReason": null,
      "error": null
    },
    {
      "step": "routing.directions",
      "wp": "ROUTE",
      "method": "POST",
      "path": "/routing/directions",
      "http": 201,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 27,
      "fields": [
        "mode",
        "distanceM",
        "durationSec",
        "provider",
        "summary",
        "polyline",
        "polyline[].lat",
        "polyline[].lng",
        "legs",
        "legs[].from",
        "legs[].from.lat",
        "legs[].from.lng",
        "legs[].to",
        "legs[].to.lat",
        "legs[].to.lng",
        "legs[].distanceM",
        "legs[].durationSec",
        "legs[].instruction",
        "steps",
        "steps[].instruction",
        "steps[].distanceM",
        "steps[].durationSec",
        "steps[].location",
        "steps[].location.lat",
        "steps[].location.lng",
        "steps[].type",
        "providerUsed"
      ],
      "missing": [],
      "sample": {
        "mode": "driving",
        "distanceM": "1041",
        "durationSec": "277",
        "provider": "mapbox",
        "summary": "1.0 km · ~5 phút",
        "polyline": "array[42]",
        "legs": "array[1]",
        "steps": "array[6]",
        "providerUsed": "mapbox"
      },
      "note": "",
      "errorCode": null,
      "businessReason": null,
      "error": null
    },
    {
      "step": "media.upload",
      "wp": "MEDIA",
      "method": "POST",
      "path": "/upload/single",
      "http": 401,
      "status": "FAIL",
      "completeness": 0,
      "fieldCount": 5,
      "fields": [
        "statusCode",
        "error",
        "message",
        "path",
        "timestamp"
      ],
      "missing": [
        "id",
        "objectKey",
        "publicUrl",
        "mimeType",
        "sizeBytes",
        "originalName",
        "kind",
        "status",
        "createdAt"
      ],
      "sample": {
        "statusCode": "401",
        "error": "UNAUTHORIZED",
        "message": "Unauthorized",
        "path": "/api/v1/upload/single",
        "timestamp": "2026-08-19T03:07:54.879Z"
      },
      "note": "",
      "errorCode": "UNAUTHORIZED",
      "businessReason": "Unauthorized",
      "error": "Unauthorized"
    },
    {
      "step": "addr.create",
      "wp": "ADDR",
      "method": "POST",
      "path": "/addresses",
      "http": 401,
      "status": "FAIL",
      "completeness": 0,
      "fieldCount": 5,
      "fields": [
        "statusCode",
        "error",
        "message",
        "path",
        "timestamp"
      ],
      "missing": [
        "id",
        "label",
        "recipientName",
        "phone",
        "line1",
        "line2",
        "ward",
        "district",
        "city",
        "country",
        "lat",
        "lng",
        "isDefault",
        "createdAt",
        "updatedAt"
      ],
      "sample": {
        "statusCode": "401",
        "error": "UNAUTHORIZED",
        "message": "Unauthorized",
        "path": "/api/v1/addresses",
        "timestamp": "2026-08-19T03:07:54.894Z"
      },
      "note": "",
      "errorCode": "UNAUTHORIZED",
      "businessReason": "Unauthorized",
      "error": "Unauthorized"
    },
    {
      "step": "addr.default",
      "wp": "ADDR",
      "method": "GET",
      "path": "/addresses/me/default",
      "http": 401,
      "status": "FAIL",
      "completeness": 0,
      "fieldCount": 5,
      "fields": [
        "statusCode",
        "error",
        "message",
        "path",
        "timestamp"
      ],
      "missing": [
        "id",
        "label",
        "line1",
        "city",
        "lat",
        "lng",
        "isDefault",
        "country"
      ],
      "sample": {
        "statusCode": "401",
        "error": "UNAUTHORIZED",
        "message": "Unauthorized",
        "path": "/api/v1/addresses/me/default",
        "timestamp": "2026-08-19T03:07:54.909Z"
      },
      "note": "",
      "errorCode": "UNAUTHORIZED",
      "businessReason": "Unauthorized",
      "error": "Unauthorized"
    },
    {
      "step": "wallet.topup",
      "wp": "WALLET",
      "method": "POST",
      "path": "/wallet/topup",
      "http": 401,
      "status": "FAIL",
      "completeness": 0,
      "fieldCount": 5,
      "fields": [
        "statusCode",
        "error",
        "message",
        "path",
        "timestamp"
      ],
      "missing": [
        "id",
        "type",
        "amount",
        "balanceAfter",
        "reason",
        "note",
        "idempotencyKey",
        "createdAt",
        "balance",
        "replayed"
      ],
      "sample": {
        "statusCode": "401",
        "error": "UNAUTHORIZED",
        "message": "Unauthorized",
        "path": "/api/v1/wallet/topup",
        "timestamp": "2026-08-19T03:07:54.925Z"
      },
      "note": "",
      "errorCode": "UNAUTHORIZED",
      "businessReason": "Unauthorized",
      "error": "Unauthorized"
    },
    {
      "step": "wallet.topup.idem",
      "wp": "WALLET",
      "method": "POST",
      "path": "/wallet/topup",
      "http": 401,
      "status": "FAIL",
      "completeness": 0,
      "fieldCount": 5,
      "fields": [
        "statusCode",
        "error",
        "message",
        "path",
        "timestamp"
      ],
      "missing": [
        "balance",
        "replayed",
        "id"
      ],
      "sample": {
        "statusCode": "401",
        "error": "UNAUTHORIZED",
        "message": "Unauthorized",
        "path": "/api/v1/wallet/topup",
        "timestamp": "2026-08-19T03:07:54.942Z"
      },
      "note": "",
      "errorCode": "UNAUTHORIZED",
      "businessReason": "Unauthorized",
      "error": "Unauthorized"
    },
    {
      "step": "wallet.balance",
      "wp": "WALLET",
      "method": "GET",
      "path": "/wallet",
      "http": 401,
      "status": "FAIL",
      "completeness": 0,
      "fieldCount": 5,
      "fields": [
        "statusCode",
        "error",
        "message",
        "path",
        "timestamp"
      ],
      "missing": [
        "accountId",
        "currency",
        "balance",
        "updatedAt"
      ],
      "sample": {
        "statusCode": "401",
        "error": "UNAUTHORIZED",
        "message": "Unauthorized",
        "path": "/api/v1/wallet",
        "timestamp": "2026-08-19T03:07:54.957Z"
      },
      "note": "",
      "errorCode": "UNAUTHORIZED",
      "businessReason": "Unauthorized",
      "error": "Unauthorized"
    },
    {
      "step": "wallet.tx",
      "wp": "WALLET",
      "method": "GET",
      "path": "/wallet/transactions",
      "http": 401,
      "status": "FAIL",
      "completeness": 0,
      "fieldCount": 5,
      "fields": [
        "statusCode",
        "error",
        "message",
        "path",
        "timestamp"
      ],
      "missing": [
        "items",
        "count",
        "balance",
        "items[].id",
        "items[].type",
        "items[].amount",
        "items[].balanceAfter",
        "items[].createdAt"
      ],
      "sample": {
        "statusCode": "401",
        "error": "UNAUTHORIZED",
        "message": "Unauthorized",
        "path": "/api/v1/wallet/transactions",
        "timestamp": "2026-08-19T03:07:54.973Z"
      },
      "note": "",
      "errorCode": "UNAUTHORIZED",
      "businessReason": "Unauthorized",
      "error": "Unauthorized"
    },
    {
      "step": "fnb.merchants",
      "wp": "FNB",
      "method": "GET",
      "path": "/merchants",
      "http": 200,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 16,
      "fields": [
        "items",
        "items[].id",
        "items[].name",
        "items[].slug",
        "items[].kind",
        "items[].description",
        "items[].address",
        "items[].phone",
        "items[].imageUrl",
        "items[].lat",
        "items[].lng",
        "items[].ratingAvg",
        "items[].isOpen",
        "items[].partnerOrgId",
        "items[].distanceM",
        "count"
      ],
      "missing": [],
      "sample": {
        "items": "array[100]",
        "count": "100"
      },
      "note": "",
      "errorCode": null,
      "businessReason": null,
      "error": null
    },
    {
      "step": "fnb.menu",
      "wp": "FNB",
      "method": "GET",
      "path": "/merchants/:id/menu",
      "http": 200,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 13,
      "fields": [
        "categories",
        "categories[].id",
        "categories[].name",
        "categories[].sortOrder",
        "categories[].items",
        "categories[].items[].id",
        "categories[].items[].name",
        "categories[].items[].description",
        "categories[].items[].price",
        "categories[].items[].isAvailable",
        "categories[].items[].imageUrl",
        "categories[].items[].categoryId",
        "uncategorized"
      ],
      "missing": [],
      "sample": {
        "categories": "array[2]",
        "uncategorized": "array[0]"
      },
      "note": "",
      "errorCode": null,
      "businessReason": null,
      "error": null
    },
    {
      "step": "fnb.cart.add",
      "wp": "FNB",
      "method": "POST",
      "path": "/cart/items",
      "http": 401,
      "status": "FAIL",
      "completeness": 0,
      "fieldCount": 5,
      "fields": [
        "statusCode",
        "error",
        "message",
        "path",
        "timestamp"
      ],
      "missing": [
        "id",
        "merchantId",
        "items",
        "subtotal",
        "items[].menuItemId",
        "items[].name",
        "items[].price",
        "items[].quantity",
        "items[].lineTotal"
      ],
      "sample": {
        "statusCode": "401",
        "error": "UNAUTHORIZED",
        "message": "Unauthorized",
        "path": "/api/v1/cart/items",
        "timestamp": "2026-08-19T03:07:55.052Z"
      },
      "note": "",
      "errorCode": "UNAUTHORIZED",
      "businessReason": "Unauthorized",
      "error": "Unauthorized"
    },
    {
      "step": "fnb.order",
      "wp": "FNB",
      "method": "POST",
      "path": "/orders",
      "http": 401,
      "status": "FAIL",
      "completeness": 0,
      "fieldCount": 5,
      "fields": [
        "statusCode",
        "error",
        "message",
        "path",
        "timestamp"
      ],
      "missing": [
        "id",
        "status",
        "subtotal",
        "discount",
        "total",
        "note",
        "addressSnapshot",
        "addressSnapshot.label",
        "addressSnapshot.line1",
        "addressSnapshot.city",
        "addressSnapshot.lat",
        "addressSnapshot.lng",
        "merchant.id",
        "merchant.name",
        "merchant.slug",
        "items",
        "items[].id",
        "items[].name",
        "items[].unitPrice",
        "items[].quantity",
        "items[].lineTotal",
        "createdAt",
        "updatedAt"
      ],
      "sample": {
        "statusCode": "401",
        "error": "UNAUTHORIZED",
        "message": "Unauthorized",
        "path": "/api/v1/orders",
        "timestamp": "2026-08-19T03:07:55.066Z"
      },
      "note": "",
      "errorCode": "UNAUTHORIZED",
      "businessReason": "Unauthorized",
      "error": "Unauthorized"
    },
    {
      "step": "ride.quote",
      "wp": "RIDE",
      "method": "POST",
      "path": "/rides/quotes",
      "http": 401,
      "status": "FAIL",
      "completeness": 0,
      "fieldCount": 5,
      "fields": [
        "statusCode",
        "error",
        "message",
        "path",
        "timestamp"
      ],
      "missing": [
        "id",
        "distanceMeters",
        "durationSec",
        "fareAmount",
        "currency",
        "expiresAt",
        "options",
        "options[].vehicle",
        "options[].fareAmount"
      ],
      "sample": {
        "statusCode": "401",
        "error": "UNAUTHORIZED",
        "message": "Unauthorized",
        "path": "/api/v1/rides/quotes",
        "timestamp": "2026-08-19T03:07:55.080Z"
      },
      "note": "",
      "errorCode": "UNAUTHORIZED",
      "businessReason": "Unauthorized",
      "error": "Unauthorized"
    },
    {
      "step": "ride.create",
      "wp": "RIDE",
      "method": "POST",
      "path": "/rides",
      "http": 401,
      "status": "FAIL",
      "completeness": 0,
      "fieldCount": 5,
      "fields": [
        "statusCode",
        "error",
        "message",
        "path",
        "timestamp"
      ],
      "missing": [
        "id",
        "quoteId",
        "status",
        "pickupLat",
        "pickupLng",
        "dropoffLat",
        "dropoffLng",
        "distanceMeters",
        "durationSec",
        "fareAmount",
        "currency",
        "cancelReason",
        "createdAt",
        "updatedAt",
        "driverId"
      ],
      "sample": {
        "statusCode": "401",
        "error": "UNAUTHORIZED",
        "message": "Unauthorized",
        "path": "/api/v1/rides",
        "timestamp": "2026-08-19T03:07:55.084Z"
      },
      "note": "driverId gap if missing",
      "errorCode": "UNAUTHORIZED",
      "businessReason": "Unauthorized",
      "error": "Unauthorized"
    },
    {
      "step": "ride.cancel",
      "wp": "RIDE",
      "method": "POST",
      "path": "/rides/:id/cancel",
      "http": 401,
      "status": "FAIL",
      "completeness": 0,
      "fieldCount": 5,
      "fields": [
        "statusCode",
        "error",
        "message",
        "path",
        "timestamp"
      ],
      "missing": [
        "id",
        "status",
        "cancelReason"
      ],
      "sample": {
        "statusCode": "401",
        "error": "UNAUTHORIZED",
        "message": "Unauthorized",
        "path": "/api/v1/rides/undefined/cancel",
        "timestamp": "2026-08-19T03:07:55.095Z"
      },
      "note": "",
      "errorCode": "UNAUTHORIZED",
      "businessReason": "Unauthorized",
      "error": "Unauthorized"
    },
    {
      "step": "driver.me.asConsumer",
      "wp": "DRV",
      "method": "GET",
      "path": "/driver/me",
      "http": 401,
      "status": "FAIL",
      "completeness": 0,
      "fieldCount": 5,
      "fields": [
        "statusCode",
        "error",
        "message",
        "path",
        "timestamp"
      ],
      "missing": [],
      "sample": {
        "statusCode": "401",
        "error": "UNAUTHORIZED",
        "message": "Unauthorized",
        "path": "/api/v1/driver/me",
        "timestamp": "2026-08-19T03:07:55.111Z"
      },
      "note": "expect 403",
      "errorCode": "UNAUTHORIZED",
      "businessReason": "Unauthorized",
      "error": "Unauthorized"
    },
    {
      "step": "auth.verify.driver",
      "wp": "AUTH",
      "method": "POST",
      "path": "/auth/otp/verify",
      "http": 200,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 20,
      "fields": [
        "accessToken",
        "refreshToken",
        "tokenType",
        "expiresInSec",
        "isNewDevice",
        "sessionId",
        "user",
        "user.id",
        "user.phone",
        "user.email",
        "user.roles",
        "surface",
        "driver",
        "driver.hasRole",
        "driver.applicationStatus",
        "driver.requiresRegistration",
        "partner",
        "partner.hasRole",
        "partner.applicationStatus",
        "partner.requiresRegistration"
      ],
      "missing": [],
      "sample": {
        "accessToken": "eyJhbGciOiJIUzI1…len=331",
        "refreshToken": "eyJhbGciOiJIUzI1…len=412",
        "tokenType": "Bearer",
        "expiresInSec": "900",
        "isNewDevice": "false",
        "sessionId": "ae7f5e0d-ad64-4fde-af35-5b66caa72bb6",
        "user": "object",
        "surface": "DRIVER",
        "driver": "object",
        "partner": "object"
      },
      "note": "",
      "errorCode": null,
      "businessReason": null,
      "error": null
    },
    {
      "step": "driver.register",
      "wp": "DRV",
      "method": "POST",
      "path": "/driver/register",
      "http": 409,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 6,
      "fields": [
        "statusCode",
        "code",
        "error",
        "message",
        "path",
        "timestamp"
      ],
      "missing": [],
      "sample": {
        "statusCode": "409",
        "code": "DRIVER_ALREADY_REGISTERED",
        "error": "Conflict",
        "message": "Đã có hồ sơ tài xế (APPROVED)",
        "path": "/api/v1/driver/register",
        "timestamp": "2026-08-19T03:07:55.171Z"
      },
      "note": "expect DRIVER_ALREADY_REGISTERED on re-run",
      "errorCode": "DRIVER_ALREADY_REGISTERED",
      "businessReason": "Đã có hồ sơ tài xế (APPROVED)",
      "error": "Đã có hồ sơ tài xế (APPROVED)"
    },
    {
      "step": "auth.verify.admin",
      "wp": "AUTH",
      "method": "POST",
      "path": "/auth/otp/verify",
      "http": 200,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 20,
      "fields": [
        "accessToken",
        "refreshToken",
        "tokenType",
        "expiresInSec",
        "isNewDevice",
        "sessionId",
        "user",
        "user.id",
        "user.phone",
        "user.email",
        "user.roles",
        "surface",
        "driver",
        "driver.hasRole",
        "driver.applicationStatus",
        "driver.requiresRegistration",
        "partner",
        "partner.hasRole",
        "partner.applicationStatus",
        "partner.requiresRegistration"
      ],
      "missing": [],
      "sample": {
        "accessToken": "eyJhbGciOiJIUzI1…len=329",
        "refreshToken": "eyJhbGciOiJIUzI1…len=411",
        "tokenType": "Bearer",
        "expiresInSec": "900",
        "isNewDevice": "false",
        "sessionId": "d2f2be0c-1a46-4f2b-8bdf-1f1c5a6c55a2",
        "user": "object",
        "surface": "CONSUMER",
        "driver": "object",
        "partner": "object"
      },
      "note": "",
      "errorCode": null,
      "businessReason": null,
      "error": null
    },
    {
      "step": "driver.admin.list",
      "wp": "DRV",
      "method": "GET",
      "path": "/driver/admin/applications",
      "http": 200,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 29,
      "fields": [
        "items",
        "items[].id",
        "items[].userId",
        "items[].fullName",
        "items[].vehicleType",
        "items[].plateNumber",
        "items[].licenseNumber",
        "items[].licenseMediaId",
        "items[].licenseBackMediaId",
        "items[].vehicleMediaId",
        "items[].selfieMediaId",
        "items[].licenseMedia",
        "items[].licenseBackMedia",
        "items[].vehicleMedia",
        "items[].selfieMedia",
        "items[].kycStatus",
        "items[].kycRejectionReason",
        "items[].kycReviewedAt",
        "items[].status",
        "items[].rejectionReason",
        "items[].isOnline",
        "items[].capabilities",
        "items[].lastLat",
        "items[].lastLng",
        "items[].ratingAvg",
        "items[].createdAt",
        "items[].updatedAt",
        "items[].reviewedAt",
        "count"
      ],
      "missing": [],
      "sample": {
        "items": "array[13]",
        "count": "13"
      },
      "note": "",
      "errorCode": null,
      "businessReason": null,
      "error": null
    },
    {
      "step": "driver.admin.approve",
      "wp": "DRV",
      "method": "PATCH",
      "path": "/driver/admin/applications/:id",
      "http": 200,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 1,
      "fields": [
        "status"
      ],
      "missing": [],
      "sample": {
        "status": "ALREADY"
      },
      "note": "no pending",
      "errorCode": null,
      "businessReason": null,
      "error": null
    },
    {
      "step": "driver.me",
      "wp": "DRV",
      "method": "GET",
      "path": "/driver/me",
      "http": 200,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 31,
      "fields": [
        "id",
        "userId",
        "fullName",
        "vehicleType",
        "plateNumber",
        "licenseNumber",
        "licenseMediaId",
        "licenseBackMediaId",
        "vehicleMediaId",
        "selfieMediaId",
        "licenseMedia",
        "licenseMedia.id",
        "licenseMedia.publicUrl",
        "licenseBackMedia",
        "vehicleMedia",
        "selfieMedia",
        "kycStatus",
        "kycRejectionReason",
        "kycReviewedAt",
        "status",
        "rejectionReason",
        "isOnline",
        "capabilities",
        "lastLat",
        "lastLng",
        "ratingAvg",
        "createdAt",
        "updatedAt",
        "reviewedAt",
        "roles",
        "hasDriverRole"
      ],
      "missing": [],
      "sample": {
        "id": "7887a648-ee8e-46cc-825a-02191ab8d84b",
        "userId": "f149c97d-5d01-4cef-b357-00724ffabd35",
        "fullName": "Nguyen Van Tai",
        "vehicleType": "BIKE",
        "plateNumber": "59A1-99999",
        "licenseNumber": "GPLX-999",
        "licenseMediaId": "5167fee9-9f6f-411f-b27a-ebc3532a600c",
        "licenseBackMediaId": "null",
        "vehicleMediaId": "null",
        "selfieMediaId": "null",
        "licenseMedia": "object",
        "licenseBackMedia": "null",
        "vehicleMedia": "null",
        "selfieMedia": "null"
      },
      "note": "",
      "errorCode": null,
      "businessReason": null,
      "error": null
    },
    {
      "step": "driver.online",
      "wp": "DRV",
      "method": "PATCH",
      "path": "/driver/status",
      "http": 200,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 29,
      "fields": [
        "id",
        "userId",
        "fullName",
        "vehicleType",
        "plateNumber",
        "licenseNumber",
        "licenseMediaId",
        "licenseBackMediaId",
        "vehicleMediaId",
        "selfieMediaId",
        "licenseMedia",
        "licenseMedia.id",
        "licenseMedia.publicUrl",
        "licenseBackMedia",
        "vehicleMedia",
        "selfieMedia",
        "kycStatus",
        "kycRejectionReason",
        "kycReviewedAt",
        "status",
        "rejectionReason",
        "isOnline",
        "capabilities",
        "lastLat",
        "lastLng",
        "ratingAvg",
        "createdAt",
        "updatedAt",
        "reviewedAt"
      ],
      "missing": [],
      "sample": {
        "id": "7887a648-ee8e-46cc-825a-02191ab8d84b",
        "userId": "f149c97d-5d01-4cef-b357-00724ffabd35",
        "fullName": "Nguyen Van Tai",
        "vehicleType": "BIKE",
        "plateNumber": "59A1-99999",
        "licenseNumber": "GPLX-999",
        "licenseMediaId": "5167fee9-9f6f-411f-b27a-ebc3532a600c",
        "licenseBackMediaId": "null",
        "vehicleMediaId": "null",
        "selfieMediaId": "null",
        "licenseMedia": "object",
        "licenseBackMedia": "null",
        "vehicleMedia": "null",
        "selfieMedia": "null"
      },
      "note": "",
      "errorCode": null,
      "businessReason": null,
      "error": null
    },
    {
      "step": "ride.passenger.create",
      "wp": "RIDE",
      "method": "POST",
      "path": "/rides",
      "http": 201,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 31,
      "fields": [
        "id",
        "quoteId",
        "driverId",
        "status",
        "pickupLat",
        "pickupLng",
        "dropoffLat",
        "dropoffLng",
        "distanceMeters",
        "durationSec",
        "fareAmount",
        "vehicleType",
        "paymentMethod",
        "paymentStatus",
        "settledAt",
        "driverEarning",
        "platformFee",
        "promoCode",
        "discountAmount",
        "currency",
        "cancelReason",
        "bookingMode",
        "pickupAddress",
        "dropoffAddress",
        "riderName",
        "riderPhone",
        "riderNote",
        "createdAt",
        "updatedAt",
        "payment",
        "payUrl"
      ],
      "missing": [],
      "sample": {
        "id": "fa252408-b055-4d3c-bd3e-3c57f9822592",
        "quoteId": "8d5eb1a3-0920-401a-bd52-b45e2389d877",
        "driverId": "1f7b8541-9701-4dfa-a088-21a4a5005d62",
        "status": "CONFIRMED",
        "pickupLat": "10.777",
        "pickupLng": "106.701",
        "dropoffLat": "10.79",
        "dropoffLng": "106.71",
        "distanceMeters": "2906",
        "durationSec": "701",
        "fareAmount": "26530",
        "vehicleType": "CAR",
        "paymentMethod": "CASH",
        "paymentStatus": "UNPAID"
      },
      "note": "driverId before accept",
      "errorCode": null,
      "businessReason": null,
      "error": null
    },
    {
      "step": "driver.available",
      "wp": "DRV",
      "method": "GET",
      "path": "/driver/trips/available",
      "http": 200,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 34,
      "fields": [
        "items",
        "items[].id",
        "items[].status",
        "items[].pickupLat",
        "items[].pickupLng",
        "items[].dropoffLat",
        "items[].dropoffLng",
        "items[].distanceMeters",
        "items[].durationSec",
        "items[].fareAmount",
        "items[].driverEarning",
        "items[].platformFee",
        "items[].promoCode",
        "items[].discountAmount",
        "items[].paymentMethod",
        "items[].paymentStatus",
        "items[].vehicleType",
        "items[].currency",
        "items[].createdAt",
        "items[].updatedAt",
        "items[].cancelReason",
        "items[].distanceToPickupM",
        "items[].passengerLocation",
        "items[].passenger",
        "items[].passenger.id",
        "items[].passenger.fullName",
        "items[].passenger.phone",
        "items[].passenger.avatarUrl",
        "items[].passenger.tripCount",
        "items[].riderNote",
        "items[].bookingMode",
        "items[].pickupAddress",
        "items[].dropoffAddress",
        "count"
      ],
      "missing": [],
      "sample": {
        "items": "array[1]",
        "count": "1"
      },
      "note": "",
      "errorCode": null,
      "businessReason": null,
      "error": null
    },
    {
      "step": "driver.accept",
      "wp": "DRV",
      "method": "POST",
      "path": "/driver/trips/:id/accept",
      "http": 400,
      "status": "FAIL",
      "completeness": 0,
      "fieldCount": 5,
      "fields": [
        "statusCode",
        "error",
        "message",
        "path",
        "timestamp"
      ],
      "missing": [
        "id",
        "status"
      ],
      "sample": {
        "statusCode": "400",
        "error": "Bad Request",
        "message": "Chuyến không còn available",
        "path": "/api/v1/driver/t…len=64",
        "timestamp": "2026-08-19T03:07:55.762Z"
      },
      "note": "",
      "errorCode": null,
      "businessReason": "Chuyến không còn available",
      "error": "Chuyến không còn available"
    },
    {
      "step": "driver.pickup",
      "wp": "DRV",
      "method": "POST",
      "path": "/driver/trips/:id/pickup",
      "http": 403,
      "status": "FAIL",
      "completeness": 0,
      "fieldCount": 5,
      "fields": [
        "statusCode",
        "error",
        "message",
        "path",
        "timestamp"
      ],
      "missing": [
        "id",
        "status"
      ],
      "sample": {
        "statusCode": "403",
        "error": "Forbidden",
        "message": "Không phải chuyến của bạn",
        "path": "/api/v1/driver/t…len=64",
        "timestamp": "2026-08-19T03:07:55.776Z"
      },
      "note": "",
      "errorCode": null,
      "businessReason": "Không phải chuyến của bạn",
      "error": "Không phải chuyến của bạn"
    },
    {
      "step": "driver.complete",
      "wp": "DRV",
      "method": "POST",
      "path": "/driver/trips/:id/complete",
      "http": 403,
      "status": "FAIL",
      "completeness": 0,
      "fieldCount": 5,
      "fields": [
        "statusCode",
        "error",
        "message",
        "path",
        "timestamp"
      ],
      "missing": [
        "id",
        "status"
      ],
      "sample": {
        "statusCode": "403",
        "error": "Forbidden",
        "message": "Không phải chuyến của bạn",
        "path": "/api/v1/driver/t…len=66",
        "timestamp": "2026-08-19T03:07:55.792Z"
      },
      "note": "",
      "errorCode": null,
      "businessReason": "Không phải chuyến của bạn",
      "error": "Không phải chuyến của bạn"
    },
    {
      "step": "driver.earnings",
      "wp": "DRV",
      "method": "GET",
      "path": "/driver/earnings",
      "http": 200,
      "status": "PASS",
      "completeness": 75,
      "fieldCount": 12,
      "fields": [
        "tripsCompleted",
        "totalFare",
        "totalEarning",
        "platformFee",
        "currency",
        "todayEarning",
        "todayTrips",
        "yesterdayEarning",
        "vsYesterdayPct",
        "cancelledTrips",
        "completionRate",
        "items"
      ],
      "missing": [
        "message"
      ],
      "sample": {
        "tripsCompleted": "0",
        "totalFare": "0",
        "totalEarning": "0",
        "platformFee": "0",
        "currency": "VND",
        "todayEarning": "0",
        "todayTrips": "0",
        "yesterdayEarning": "0",
        "vsYesterdayPct": "null",
        "cancelledTrips": "0",
        "completionRate": "0",
        "items": "array[0]"
      },
      "note": "",
      "errorCode": null,
      "businessReason": null,
      "error": null
    },
    {
      "step": "ride.detail.after",
      "wp": "RIDE",
      "method": "GET",
      "path": "/rides/:id",
      "http": 200,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 39,
      "fields": [
        "id",
        "quoteId",
        "driverId",
        "status",
        "pickupLat",
        "pickupLng",
        "dropoffLat",
        "dropoffLng",
        "distanceMeters",
        "durationSec",
        "fareAmount",
        "vehicleType",
        "paymentMethod",
        "paymentStatus",
        "settledAt",
        "driverEarning",
        "platformFee",
        "promoCode",
        "discountAmount",
        "currency",
        "cancelReason",
        "bookingMode",
        "pickupAddress",
        "dropoffAddress",
        "riderName",
        "riderPhone",
        "riderNote",
        "createdAt",
        "updatedAt",
        "driver",
        "driver.id",
        "driver.fullName",
        "driver.phone",
        "driver.avatarUrl",
        "driver.vehicleType",
        "driver.plateNumber",
        "driver.ratingAvg",
        "driver.lastLat",
        "driver.lastLng"
      ],
      "missing": [],
      "sample": {
        "id": "fa252408-b055-4d3c-bd3e-3c57f9822592",
        "quoteId": "8d5eb1a3-0920-401a-bd52-b45e2389d877",
        "driverId": "1f7b8541-9701-4dfa-a088-21a4a5005d62",
        "status": "CONFIRMED",
        "pickupLat": "10.777",
        "pickupLng": "106.701",
        "dropoffLat": "10.79",
        "dropoffLng": "106.71",
        "distanceMeters": "2906",
        "durationSec": "701",
        "fareAmount": "26530",
        "vehicleType": "CAR",
        "paymentMethod": "CASH",
        "paymentStatus": "UNPAID"
      },
      "note": "",
      "errorCode": null,
      "businessReason": null,
      "error": null
    },
    {
      "step": "auth.verify.partner",
      "wp": "AUTH",
      "method": "POST",
      "path": "/auth/otp/verify",
      "http": 200,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 20,
      "fields": [
        "accessToken",
        "refreshToken",
        "tokenType",
        "expiresInSec",
        "isNewDevice",
        "sessionId",
        "user",
        "user.id",
        "user.phone",
        "user.email",
        "user.roles",
        "surface",
        "driver",
        "driver.hasRole",
        "driver.applicationStatus",
        "driver.requiresRegistration",
        "partner",
        "partner.hasRole",
        "partner.applicationStatus",
        "partner.requiresRegistration"
      ],
      "missing": [],
      "sample": {
        "accessToken": "eyJhbGciOiJIUzI1…len=340",
        "refreshToken": "eyJhbGciOiJIUzI1…len=421",
        "tokenType": "Bearer",
        "expiresInSec": "900",
        "isNewDevice": "false",
        "sessionId": "90bb5709-bebc-4882-b5d8-d948b7fcda9a",
        "user": "object",
        "surface": "PARTNER",
        "driver": "object",
        "partner": "object"
      },
      "note": "",
      "errorCode": null,
      "businessReason": null,
      "error": null
    },
    {
      "step": "partner.onboarding",
      "wp": "PAR",
      "method": "POST",
      "path": "/partners/onboarding",
      "http": 409,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 6,
      "fields": [
        "statusCode",
        "code",
        "error",
        "message",
        "path",
        "timestamp"
      ],
      "missing": [],
      "sample": {
        "statusCode": "409",
        "code": "PARTNER_ALREADY_REGISTERED",
        "error": "Conflict",
        "message": "Đã có hồ sơ partner (APPROVED)",
        "path": "/api/v1/partners/onboarding",
        "timestamp": "2026-08-19T03:07:55.884Z"
      },
      "note": "expect PARTNER_ALREADY_REGISTERED on re-run",
      "errorCode": "PARTNER_ALREADY_REGISTERED",
      "businessReason": "Đã có hồ sơ partner (APPROVED)",
      "error": "Đã có hồ sơ partner (APPROVED)"
    },
    {
      "step": "partner.admin.list",
      "wp": "PAR",
      "method": "GET",
      "path": "/partners/admin/applications",
      "http": 200,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 13,
      "fields": [
        "items",
        "items[].id",
        "items[].ownerUserId",
        "items[].businessName",
        "items[].businessType",
        "items[].address",
        "items[].taxCode",
        "items[].status",
        "items[].rejectionReason",
        "items[].createdAt",
        "items[].updatedAt",
        "items[].reviewedAt",
        "count"
      ],
      "missing": [],
      "sample": {
        "items": "array[4]",
        "count": "4"
      },
      "note": "",
      "errorCode": null,
      "businessReason": null,
      "error": null
    },
    {
      "step": "partner.admin.approve",
      "wp": "PAR",
      "method": "PATCH",
      "path": "/partners/admin/applications/:id",
      "http": 200,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 11,
      "fields": [
        "id",
        "ownerUserId",
        "businessName",
        "businessType",
        "address",
        "taxCode",
        "status",
        "rejectionReason",
        "createdAt",
        "updatedAt",
        "reviewedAt"
      ],
      "missing": [],
      "sample": {
        "id": "6ba249ba-9486-4ad5-8269-04142d86d22f",
        "ownerUserId": "bb856f68-7e27-445f-88f3-2bf9345fda34",
        "businessName": "Smoke Partner Cafe",
        "businessType": "FNB",
        "address": "Q1",
        "taxCode": "0312345678",
        "status": "APPROVED",
        "rejectionReason": "null",
        "createdAt": "2026-07-24T06:48:49.682Z",
        "updatedAt": "2026-08-19T03:07:55.925Z",
        "reviewedAt": "2026-08-19T03:07:55.923Z"
      },
      "note": "",
      "errorCode": null,
      "businessReason": null,
      "error": null
    },
    {
      "step": "partner.me",
      "wp": "PAR",
      "method": "GET",
      "path": "/partners/me",
      "http": 200,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 15,
      "fields": [
        "id",
        "ownerUserId",
        "businessName",
        "businessType",
        "address",
        "taxCode",
        "status",
        "rejectionReason",
        "createdAt",
        "updatedAt",
        "reviewedAt",
        "roles",
        "hasPartnerRole",
        "membershipKind",
        "roleLabel"
      ],
      "missing": [],
      "sample": {
        "id": "6ba249ba-9486-4ad5-8269-04142d86d22f",
        "ownerUserId": "bb856f68-7e27-445f-88f3-2bf9345fda34",
        "businessName": "Smoke Partner Cafe",
        "businessType": "FNB",
        "address": "Q1",
        "taxCode": "0312345678",
        "status": "APPROVED",
        "rejectionReason": "null",
        "createdAt": "2026-07-24T06:48:49.682Z",
        "updatedAt": "2026-08-19T03:07:55.925Z",
        "reviewedAt": "2026-08-19T03:07:55.923Z",
        "roles": "array[2]",
        "hasPartnerRole": "true",
        "membershipKind": "OWNER"
      },
      "note": "",
      "errorCode": null,
      "businessReason": null,
      "error": null
    },
    {
      "step": "partner.staff.asUser",
      "wp": "PAR",
      "method": "GET",
      "path": "/partners/staff",
      "http": 401,
      "status": "FAIL",
      "completeness": 0,
      "fieldCount": 5,
      "fields": [
        "statusCode",
        "error",
        "message",
        "path",
        "timestamp"
      ],
      "missing": [],
      "sample": {
        "statusCode": "401",
        "error": "UNAUTHORIZED",
        "message": "Unauthorized",
        "path": "/api/v1/partners/staff",
        "timestamp": "2026-08-19T03:07:55.954Z"
      },
      "note": "expect 403",
      "errorCode": "UNAUTHORIZED",
      "businessReason": "Unauthorized",
      "error": "Unauthorized"
    },
    {
      "step": "partner.staff",
      "wp": "PAR",
      "method": "GET",
      "path": "/partners/staff",
      "http": 200,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 8,
      "fields": [
        "items",
        "items[].id",
        "items[].phone",
        "items[].fullName",
        "items[].roleLabel",
        "items[].active",
        "items[].userId",
        "count"
      ],
      "missing": [],
      "sample": {
        "items": "array[16]",
        "count": "16"
      },
      "note": "",
      "errorCode": null,
      "businessReason": null,
      "error": null
    },
    {
      "step": "partner.staff.add",
      "wp": "PAR",
      "method": "POST",
      "path": "/partners/staff",
      "http": 201,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 6,
      "fields": [
        "id",
        "phone",
        "fullName",
        "roleLabel",
        "active",
        "userId"
      ],
      "missing": [],
      "sample": {
        "id": "8a559ca7-2a4d-4a11-a387-50f4a66a52df",
        "phone": "+84908875968",
        "fullName": "Staff Smoke",
        "roleLabel": "CASHIER",
        "active": "true",
        "userId": "ed3cdf55-62e3-4dce-992b-80a0c7dee13b"
      },
      "note": "",
      "errorCode": null,
      "businessReason": null,
      "error": null
    },
    {
      "step": "partner.analytics",
      "wp": "PAR",
      "method": "GET",
      "path": "/partners/analytics/overview",
      "http": 200,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 4,
      "fields": [
        "orgId",
        "businessName",
        "orderCount",
        "message"
      ],
      "missing": [],
      "sample": {
        "orgId": "6ba249ba-9486-4ad5-8269-04142d86d22f",
        "businessName": "Smoke Partner Cafe",
        "orderCount": "0",
        "message": "MVP: overview sơ…len=45"
      },
      "note": "",
      "errorCode": null,
      "businessReason": null,
      "error": null
    },
    {
      "step": "parking.nearby",
      "wp": "PARK",
      "method": "GET",
      "path": "/parking/lots/nearby",
      "http": 200,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 14,
      "fields": [
        "items",
        "items[].id",
        "items[].name",
        "items[].address",
        "items[].lat",
        "items[].lng",
        "items[].capacity",
        "items[].available",
        "items[].pricePerHour",
        "items[].openNow",
        "items[].partnerOrgId",
        "items[].imageUrl",
        "items[].distanceM",
        "count"
      ],
      "missing": [],
      "sample": {
        "items": "array[11]",
        "count": "11"
      },
      "note": "",
      "errorCode": null,
      "businessReason": null,
      "error": null
    },
    {
      "step": "parking.checkin",
      "wp": "PARK",
      "method": "POST",
      "path": "/parking/partner/check-in",
      "http": 201,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 7,
      "fields": [
        "id",
        "lotId",
        "plateNumber",
        "partnerUserId",
        "checkedInAt",
        "checkedOutAt",
        "available"
      ],
      "missing": [],
      "sample": {
        "id": "99c9f9f0-500a-4b21-8d9f-b9aa157a2a9b",
        "lotId": "4fa0b9eb-a03f-432a-97b3-81a591e0f69b",
        "plateNumber": "SM876052",
        "partnerUserId": "bb856f68-7e27-445f-88f3-2bf9345fda34",
        "checkedInAt": "2026-08-19T03:07:56.084Z",
        "checkedOutAt": "null",
        "available": "81"
      },
      "note": "lot full ok",
      "errorCode": null,
      "businessReason": null,
      "error": null
    },
    {
      "step": "parking.checkout",
      "wp": "PARK",
      "method": "POST",
      "path": "/parking/partner/check-out",
      "http": 201,
      "status": "PASS",
      "completeness": 100,
      "fieldCount": 11,
      "fields": [
        "id",
        "lotId",
        "plateNumber",
        "partnerUserId",
        "checkedInAt",
        "checkedOutAt",
        "hours",
        "amount",
        "currency",
        "available",
        "checkedOutBy"
      ],
      "missing": [],
      "sample": {
        "id": "99c9f9f0-500a-4b21-8d9f-b9aa157a2a9b",
        "lotId": "4fa0b9eb-a03f-432a-97b3-81a591e0f69b",
        "plateNumber": "SM876052",
        "partnerUserId": "bb856f68-7e27-445f-88f3-2bf9345fda34",
        "checkedInAt": "2026-08-19T03:07:56.084Z",
        "checkedOutAt": "2026-08-19T03:07:56.106Z",
        "hours": "1",
        "amount": "20000",
        "currency": "VND",
        "available": "82",
        "checkedOutBy": "bb856f68-7e27-445f-88f3-2bf9345fda34"
      },
      "note": "",
      "errorCode": null,
      "businessReason": null,
      "error": null
    }
  ]
}