{
  "id": "fix-4273-workflow-action-campaign-attribution",
  "title": "Set Campaign workflow-action CampaignMember creation populates Lead First/Last Campaign attribution",
  "kind": "hubspot_sync",
  "optional": true,
  "targetedAcceptance": {
    "schemaVersion": "hubspot-targeted-acceptance/v1",
    "reason": "Set Campaign regression for #4273/#4284 Campaign attribution."
  },
  "executionMode": "serial",
  "executionModeReason": "One ordinary HubSpot inbound contact must first materialize as a Lead, then one signed Set Campaign workflow-action call is correlated end-to-end to that stable Lead's attribution fields; run isolated so unrelated CampaignMember-triggered Flow work cannot share the window.",
  "caseTimeoutMs": 720000,
  "linkedIssues": [4273],
  "provenance": {
    "businessScenario": "K-CAMP-4273 - a CampaignMember created via the real Set Campaign path (connector_action / workflow-action webhook, ConnectorSyncOrigin='hubspot-crm-connector') must still reach the same Lead_Set_First_And_Last_CampaignMember lookup/update path as a REST-created CampaignMember. Before the #4284 fix, the Flow terminated at the L2 decision SkipConnectorInboundCampaignDerived for connector-origin CampaignMembers, leaving Lead.First_Campaign__c and Lead.Last_Campaign__c null (see #4273 for the original PROD reproduction). This case creates one real HubSpot contact, waits for the ordinary inbound path to materialize its stable NexusCRM Lead, adds that existing Lead to one fresh Campaign through the signed Set Campaign workflow-action, and asserts First_Campaign__c and Last_Campaign__c both resolve to that Campaign.",
    "reportedBy": "jiwei2021",
    "capturedAt": "2026-07-23",
    "calibrated": "Single connector-origin CampaignMember creation is sufficient to reproduce the reported defect (both attribution fields null on the first-ever membership); a second campaign/second Set Campaign call to distinguish First vs Last ordering is out of scope for this targeted regression and is covered by the general k-camp-* suite for non-defective paths."
  },
  "steps": [
    {
      "id": "create-campaign",
      "system": "nexuscrm",
      "authRole": "admin",
      "method": "POST",
      "path": "/services/data/v63.0/sobjects/Campaign",
      "body": {
        "Name": "IT Fix-4273 Campaign Attribution {{__runId}}",
        "IsActive": true
      },
      "expectStatusRange": [200, 299],
      "assertions": [
        { "path": "response.body.id", "exists": true }
      ]
    },
    {
      "id": "create-hubspot-contact",
      "system": "hubspot",
      "method": "POST",
      "path": "/crm/v3/objects/contacts/batch/create",
      "generate": {
        "count": 1,
        "into": "inputs",
        "itemTemplate": {
          "properties": {
            "email": "fix4273-{{__runId}}@example.com",
            "firstname": "Fix4273",
            "lastname": "CampaignAttribution{{__runId}}",
            "lifecyclestage": "lead"
          }
        }
      },
      "expectStatusRange": [200, 299],
      "assertions": [
        { "path": "response.body.results", "lengthAtLeast": 1 }
      ]
    },
    {
      "id": "wait-lead-materialized",
      "system": "nexuscrm",
      "authRole": "admin",
      "method": "GET",
      "path": "/services/data/v63.0/query?q=SELECT Id,HubSpot_Id__c FROM Lead WHERE HubSpot_Id__c='{{steps.create-hubspot-contact.response.body.results[0].id}}' LIMIT 1",
      "expectStatus": 200,
      "poll": { "budgetMs": 300000, "intervalMs": 10000 },
      "onTimeout": "fail",
      "assertions": [
        { "path": "response.body.records", "lengthAtLeast": 1 },
        { "path": "response.body.records[0].HubSpot_Id__c", "equals": "{{steps.create-hubspot-contact.response.body.results[0].id}}" }
      ]
    },
    {
      "id": "execute-set-campaign",
      "system": "connector_action",
      "path": "/webhooks/hubspot-crm-connector/workflow-action",
      "forEach": "steps.create-hubspot-contact.response.body.results",
      "contactIdField": "id",
      "emailField": "properties.email",
      "campaignId": "{{steps.create-campaign.response.body.id}}",
      "status": "Sent",
      "callbackIdPrefix": "fix4273-campaign-attribution",
      "concurrency": 1,
      "assertions": [
        { "path": "response.body.failedCount", "numericEquals": 0 },
        { "path": "response.body.acceptedCount", "numericEquals": 1 }
      ]
    },
    {
      "id": "assert-lead-campaign-attribution",
      "system": "nexuscrm",
      "authRole": "admin",
      "method": "GET",
      "path": "/services/data/v63.0/query?q=SELECT Id,HubSpot_Id__c,First_Campaign__c,Last_Campaign__c FROM Lead WHERE Id='{{steps.wait-lead-materialized.response.body.records[0].Id}}' LIMIT 1",
      "expectStatus": 200,
      "poll": { "budgetMs": 300000, "intervalMs": 10000 },
      "onTimeout": "fail",
      "assertions": [
        { "path": "response.body.records", "lengthAtLeast": 1 },
        { "path": "response.body.records[0].HubSpot_Id__c", "equals": "{{steps.create-hubspot-contact.response.body.results[0].id}}" },
        { "path": "response.body.records[0].First_Campaign__c", "equals": "{{steps.create-campaign.response.body.id}}" },
        { "path": "response.body.records[0].Last_Campaign__c", "equals": "{{steps.create-campaign.response.body.id}}" }
      ]
    },
    {
      "id": "assert-campaignmember-created",
      "system": "nexuscrm",
      "authRole": "admin",
      "method": "GET",
      "path": "/services/data/v63.0/query?q=SELECT COUNT() FROM CampaignMember WHERE CampaignId='{{steps.create-campaign.response.body.id}}' AND LeadId='{{steps.wait-lead-materialized.response.body.records[0].Id}}'",
      "expectStatus": 200,
      "assertions": [
        { "path": "response.body.totalSize", "numericEquals": 1 }
      ]
    }
  ]
}
