{
  "id": "k-camp-11",
  "title": "Set Campaign action option loading health (editor-time dynamic fields)",
  "kind": "hubspot_sync",
  "caseTimeoutMs": 180000,
  "provenance": {
    "businessScenario": "Config-time companion to k-camp-05. When a HubSpot workflow editor opens the 'Set NexusCRM Campaign' action, HubSpot calls the connector's options adapter to populate the Campaign and status dropdowns. A failure there surfaces in the editor as: '\"NexusCRM Campaign\" options could not load due to a 3rd-party API failure. To load please refresh the page.' This case replays that exact editor-time fetch so the failure is exposed as a real FAIL, independent of the action-execution path (k-camp-05).",
    "endpointContract": "GET /hubspot/workflow-actions/options/{health|campaigns|statuses} on the NexusCRM host, served by the workflow options adapter (deployments/offline/runtime/hubspot_workflow_options_adapter.py) behind nginx location /hubspot/workflow-actions/options/. Auth is a shared options_token (query/body), NOT X-HubSpot-Signature-v3 — distinct from the signed workflow-action. The runner injects the token from the environment (target-aware *_HUBSPOT_ACTION_OPTIONS_TOKEN); a missing token BLOCKs (env-inactive). campaigns => {searchable:true, options:[{label,value}]}; statuses(campaign_id) => {searchable:false, options:[{label,value,description}]}.",
    "reportedBy": "HubSpot sandbox workflow editor — 'options could not load (3rd-party API failure)'",
    "capturedAt": "2026-06-29",
    "assertionModel": "s2 searches campaigns by the unique runId (q={{__runId}} -> adapter Name LIKE) and asserts the dropdown actually contains the step-1 Campaign by value=its Id — i.e. the freshly created Campaign is selectable — not merely that the list is non-empty (which any pre-existing active campaign would satisfy, and which the ORDER BY Name LIMIT 100 could hide). s3 asserts the status dropdown for that Campaign offers 'Sent'.",
    "calibrated": "[calibrated] endpoints verified live on staging: /options/health=200 {ok:true}; /options/campaigns & /options/statuses reachable and options_token-gated (401 without token)"
  },
  "steps": [
    {
      "id": "s0-create-campaign",
      "system": "nexuscrm",
      "authRole": "admin",
      "method": "POST",
      "path": "/services/data/v63.0/sobjects/Campaign",
      "body": {
        "Name": "IT K-CAMP-11 options {{__runId}}",
        "IsActive": true
      },
      "expectStatusRange": [
        200,
        299
      ],
      "assertions": [
        {
          "path": "response.body.id",
          "exists": true
        }
      ]
    },
    {
      "id": "s1-options-health",
      "system": "connector_options",
      "method": "GET",
      "path": "/hubspot/workflow-actions/options/health",
      "expectStatus": 200,
      "assertions": [
        {
          "path": "response.body.ok",
          "equals": true
        }
      ]
    },
    {
      "id": "s2-options-campaigns",
      "system": "connector_options",
      "method": "GET",
      "path": "/hubspot/workflow-actions/options/campaigns?q={{__runId}}",
      "expectStatus": 200,
      "poll": {
        "budgetMs": 60000,
        "intervalMs": 8000
      },
      "onTimeout": "fail",
      "assertions": [
        {
          "path": "response.body.searchable",
          "equals": true
        },
        {
          "path": "response.body.options",
          "arrayContainsObject": {
            "value": "{{steps.s0-create-campaign.response.body.id}}"
          }
        }
      ]
    },
    {
      "id": "s3-options-statuses",
      "system": "connector_options",
      "method": "GET",
      "path": "/hubspot/workflow-actions/options/statuses?campaign_id={{steps.s0-create-campaign.response.body.id}}",
      "expectStatus": 200,
      "poll": {
        "budgetMs": 60000,
        "intervalMs": 8000
      },
      "onTimeout": "fail",
      "assertions": [
        {
          "path": "response.body.options",
          "arrayContainsObject": {
            "value": "Sent"
          }
        }
      ]
    }
  ]
}
