{
  "id": "workflow-action-identity-collision",
  "title": "Set Campaign fails closed when a new HubSpot id collides with an existing same-email person",
  "kind": "hubspot_sync",
  "optional": true,
  "targetedAcceptance": {
    "schemaVersion": "hubspot-targeted-acceptance/v1",
    "reason": "Set Campaign regression for fail-closed workflow-action identity collisions."
  },
  "caseTimeoutMs": 300000,
  "linkedIssues": [4041],
  "provenance": {
    "businessScenario": "After the 2026-07-17 duplicate-Lead incident, a Set Campaign workflow action carrying a nonblank HubSpot contact id with no exact binding or merge alias must not create a new Lead when an active same-email Lead already exists. It must fail closed with HUBSPOT_WORKFLOW_ACTION_IDENTITY_UNRESOLVED, leave the existing Lead unbound, and create no CampaignMember.",
    "reportedBy": "Amber / prod duplicate Lead RCA 2026-07-17",
    "capturedAt": "2026-07-17"
  },
  "steps": [
    {
      "id": "create-campaign",
      "system": "nexuscrm",
      "authRole": "admin",
      "method": "POST",
      "path": "/services/data/v63.0/sobjects/Campaign",
      "body": {
        "Name": "IT Workflow Identity Collision {{__runId}}",
        "IsActive": true
      },
      "expectStatusRange": [200, 299],
      "assertions": [
        { "path": "response.body.id", "exists": true }
      ]
    },
    {
      "id": "create-existing-lead",
      "system": "nexuscrm",
      "authRole": "admin",
      "method": "POST",
      "path": "/services/data/v63.0/sobjects/Lead",
      "body": {
        "LastName": "WorkflowIdentity{{__runId}}",
        "Company": "Workflow Identity Collision",
        "Email": "workflow-identity-{{__runId}}@example.com",
        "HubSpot_Sync_Enabled__c": false
      },
      "expectStatusRange": [200, 299],
      "assertions": [
        { "path": "response.body.id", "exists": true }
      ]
    },
    {
      "id": "create-contact",
      "system": "hubspot",
      "method": "POST",
      "path": "/crm/v3/objects/contacts/batch/create",
      "generate": {
        "count": 1,
        "into": "inputs",
        "itemTemplate": {
          "properties": {
            "email": "workflow-identity-{{__runId}}@example.com",
            "firstname": "Workflow",
            "lastname": "Identity{{__runId}}",
            "company": "Workflow Identity Collision",
            "lifecyclestage": "lead"
          }
        }
      },
      "expectStatusRange": [200, 299],
      "assertions": [
        { "path": "response.body.results", "lengthAtLeast": 1 }
      ]
    },
    {
      "id": "execute-set-campaign",
      "system": "connector_action",
      "path": "/webhooks/hubspot-crm-connector/workflow-action",
      "forEach": "steps.create-contact.response.body.results",
      "contactIdField": "id",
      "emailField": "properties.email",
      "campaignId": "{{steps.create-campaign.response.body.id}}",
      "status": "Sent",
      "concurrency": 1,
      "assertions": [
        { "path": "response.body.failedCount", "numericEquals": 0 },
        { "path": "response.body.acceptedCount", "numericEquals": 1 }
      ]
    },
    {
      "id": "assert-workflow-action-failed-closed",
      "system": "tidb",
      "method": "GET",
      "sql": "SELECT Id, Status, LEFT(COALESCE(LastError, ''), 500) AS LastErrorSample FROM `_System_ConnectorEvent` WHERE Namespace = 'hubspot-crm-connector' AND EventKind = 'workflow.action.execute' AND SourceObjectID = '{{steps.create-contact.response.body.results[0].id}}' AND Status IN ('failed', 'dead') AND LastError LIKE '%HUBSPOT_WORKFLOW_ACTION_IDENTITY_UNRESOLVED%' ORDER BY CreatedDate DESC LIMIT 1",
      "expectStatus": 200,
      "poll": {
        "budgetMs": 180000,
        "intervalMs": 6000
      },
      "onTimeout": "fail",
      "assertions": [
        { "path": "response.body.records", "lengthAtLeast": 1 },
        {
          "path": "response.body.records[0].LastErrorSample",
          "includes": "HUBSPOT_WORKFLOW_ACTION_IDENTITY_UNRESOLVED"
        }
      ]
    },
    {
      "id": "assert-no-remote-id-lead-created",
      "system": "tidb",
      "method": "GET",
      "sql": "SELECT COUNT(*) AS RemoteIdLeadCount FROM Lead WHERE HubSpot_Id__c = '{{steps.create-contact.response.body.results[0].id}}' AND IsConverted = 0",
      "expectStatus": 200,
      "assertions": [
        { "path": "response.body.records[0].RemoteIdLeadCount", "equals": 0 }
      ]
    },
    {
      "id": "assert-existing-lead-remains-unbound",
      "system": "tidb",
      "method": "GET",
      "sql": "SELECT COUNT(*) AS UnboundLeadCount FROM Lead WHERE Id = '{{steps.create-existing-lead.response.body.id}}' AND HubSpot_Id__c IS NULL AND IsConverted = 0",
      "expectStatus": 200,
      "assertions": [
        { "path": "response.body.records[0].UnboundLeadCount", "equals": 1 }
      ]
    },
    {
      "id": "assert-no-campaign-member-created",
      "system": "tidb",
      "method": "GET",
      "sql": "SELECT COUNT(*) AS CampaignMemberCount FROM CampaignMember WHERE CampaignId = '{{steps.create-campaign.response.body.id}}' AND LeadId = '{{steps.create-existing-lead.response.body.id}}'",
      "expectStatus": 200,
      "assertions": [
        { "path": "response.body.records[0].CampaignMemberCount", "equals": 0 }
      ]
    }
  ]
}
