{
  "description": "Test vectors for per-layer unit key resolution (multi-entity randomization). layer_user_ui hashes on the project default (userId), while layer_merchant_pricing overrides to merchantId.",
  "bundle": "bundle_per_layer_unit_key.json",
  "testCases": [
    {
      "name": "both_keys_present",
      "comment": "Both userId and merchantId are in context. Each layer hashes on its own unit key independently.",
      "context": {
        "userId": "user-abc",
        "merchantId": "merchant-1"
      },
      "expectedHashing": {
        "layer_user_ui": {
          "unitKeyValue": "user-abc",
          "bucket": 641,
          "comment": "SHA-256 v2 hash of 'user-abc:layer_user_ui' mod 1000"
        },
        "layer_merchant_pricing": {
          "unitKeyValue": "merchant-1",
          "bucket": 764,
          "comment": "SHA-256 v2 hash of 'merchant-1:layer_merchant_pricing' mod 1000"
        }
      },
      "expectedAssignments": {
        "ui.theme": "dark",
        "pricing.merchantDiscount": 15
      },
      "expectedLayers": [
        {
          "layerId": "layer_user_ui",
          "bucket": 641,
          "policyId": "policy_ui_theme",
          "allocationName": "dark_mode",
          "comment": "No unitKey/unitKeyValue — layer uses project default"
        },
        {
          "layerId": "layer_merchant_pricing",
          "bucket": 764,
          "policyId": "policy_merchant_discount",
          "allocationName": "discount_15",
          "unitKey": "merchantId",
          "unitKeyValue": "merchant-1",
          "comment": "Layer overrides unitKey to merchantId"
        }
      ]
    },
    {
      "name": "different_merchant_different_bucket",
      "comment": "Same user, different merchant — the user-scoped layer resolves identically while the merchant-scoped layer gets a different bucket.",
      "context": {
        "userId": "user-xyz",
        "merchantId": "merchant-42"
      },
      "expectedHashing": {
        "layer_user_ui": {
          "unitKeyValue": "user-xyz",
          "bucket": 872,
          "comment": "SHA-256 v2 hash of 'user-xyz:layer_user_ui' mod 1000"
        },
        "layer_merchant_pricing": {
          "unitKeyValue": "merchant-42",
          "bucket": 542,
          "comment": "SHA-256 v2 hash of 'merchant-42:layer_merchant_pricing' mod 1000"
        }
      },
      "expectedAssignments": {
        "ui.theme": "dark",
        "pricing.merchantDiscount": 15
      },
      "expectedLayers": [
        {
          "layerId": "layer_user_ui",
          "bucket": 872,
          "policyId": "policy_ui_theme",
          "allocationName": "dark_mode"
        },
        {
          "layerId": "layer_merchant_pricing",
          "bucket": 542,
          "policyId": "policy_merchant_discount",
          "allocationName": "discount_15",
          "unitKey": "merchantId",
          "unitKeyValue": "merchant-42"
        }
      ]
    },
    {
      "name": "merchant_key_missing",
      "comment": "merchantId absent from context. The merchant-scoped layer is skipped (bucket -1, no override applied), while the user-scoped layer resolves normally.",
      "context": {
        "userId": "user-abc"
      },
      "expectedHashing": {
        "layer_user_ui": {
          "unitKeyValue": "user-abc",
          "bucket": 641,
          "comment": "SHA-256 v2 hash of 'user-abc:layer_user_ui' mod 1000"
        },
        "layer_merchant_pricing": {
          "bucket": -1,
          "comment": "Layer skipped — merchantId not in context"
        }
      },
      "expectedAssignments": {
        "ui.theme": "dark",
        "pricing.merchantDiscount": 0
      },
      "expectedLayers": [
        {
          "layerId": "layer_user_ui",
          "bucket": 641,
          "policyId": "policy_ui_theme",
          "allocationName": "dark_mode"
        },
        {
          "layerId": "layer_merchant_pricing",
          "bucket": -1,
          "unitKey": "merchantId",
          "unitKeyValue": "",
          "comment": "Skipped layer still emitted with bucket -1 for decision event completeness"
        }
      ]
    },
    {
      "name": "project_unit_key_missing",
      "comment": "userId absent from context but merchantId present. The user-scoped layer is skipped while the merchant-scoped layer resolves normally.",
      "context": {
        "merchantId": "merchant-1"
      },
      "expectedHashing": {
        "layer_user_ui": {
          "bucket": -1,
          "comment": "Layer skipped — project unitKey (userId) not in context"
        },
        "layer_merchant_pricing": {
          "unitKeyValue": "merchant-1",
          "bucket": 764,
          "comment": "SHA-256 v2 hash of 'merchant-1:layer_merchant_pricing' mod 1000"
        }
      },
      "expectedAssignments": {
        "ui.theme": "light",
        "pricing.merchantDiscount": 15
      },
      "expectedLayers": [
        {
          "layerId": "layer_user_ui",
          "bucket": -1,
          "comment": "Skipped — no userId in context"
        },
        {
          "layerId": "layer_merchant_pricing",
          "bucket": 764,
          "policyId": "policy_merchant_discount",
          "allocationName": "discount_15",
          "unitKey": "merchantId",
          "unitKeyValue": "merchant-1"
        }
      ]
    },
    {
      "name": "both_keys_missing",
      "comment": "Neither userId nor merchantId in context. Both layers are skipped. Bundle parameter defaults are returned.",
      "context": {},
      "expectedHashing": {
        "layer_user_ui": {
          "bucket": -1,
          "comment": "No userId"
        },
        "layer_merchant_pricing": {
          "bucket": -1,
          "comment": "No merchantId"
        }
      },
      "expectedAssignments": {
        "ui.theme": "light",
        "pricing.merchantDiscount": 0
      },
      "expectedLayers": [
        {
          "layerId": "layer_user_ui",
          "bucket": -1
        },
        {
          "layerId": "layer_merchant_pricing",
          "bucket": -1,
          "unitKey": "merchantId",
          "unitKeyValue": ""
        }
      ]
    }
  ]
}
