{
  "id": "prod-worker-guard",
  "title": "HubSpot integration evidence must not be claimed by the production connector worker",
  "kind": "hubspot_sync",
  "caseTimeoutMs": 60000,
  "linkedIssues": [],
  "provenance": {
    "businessScenario": "生成PR一个HubSpot的Integration Test,防止此类问题再次发生。\nHubSpot的Integration Test 的case用例",
    "reportedBy": "Amber",
    "capturedAt": "2026-07-01",
    "calibrated": "[calibrated] read-only TiDB guard aligned with the worker preflight semantics (PR #4102 / issue #4100): fail on denied prod-worker identity holding any live (non-terminal) claim, or a terminal footprint whose latest activity is within 30 minutes, or a row with no parsable timestamp (fail closed). Timestamp columns referenced: ProcessedAt/ClaimedAt/CreatedDate (verified live via preflight artifact samples 2026-07-17) plus LastModifiedDate (written unconditionally on this table by the reset/quarantine SQL at deployments/offline/runtime/common.py:3228,3305, so terminalization stamped only there still counts as fresh). An earlier review-thread claim that this table lacks LastModifiedDate was retracted: the quarantine SQL writes the column unconditionally and reset deploys succeed, proving it exists. UpdatedAt is deliberately absent: no maintained code writes it on this table and a non-existent column reference would turn the guard into an SQL error. Aged terminal foreign history is tolerated because a reset-from-prod snapshot copies prod terminal events into staging/test evidence."
  },
  "steps": [
    {
      "id": "assert-no-prod-worker-claims",
      "system": "tidb",
      "method": "GET",
      "sql": "SELECT Id, Status, ClaimedBy, SourceObjectID, CreatedDate, ClaimedAt, ProcessedAt, LastModifiedDate FROM `_System_ConnectorEvent` WHERE Namespace = 'hubspot-crm-connector' AND ClaimedBy LIKE CONCAT('%', '{{hubspot.connectorWorkerDeniedClaimedByNeedle}}', '%') AND (LOWER(COALESCE(Status, '')) NOT IN ('processed', 'skipped', 'dead') OR ProcessedAt >= DATE_SUB(UTC_TIMESTAMP(), INTERVAL 30 MINUTE) OR LastModifiedDate >= DATE_SUB(UTC_TIMESTAMP(), INTERVAL 30 MINUTE) OR ClaimedAt >= DATE_SUB(UTC_TIMESTAMP(), INTERVAL 30 MINUTE) OR CreatedDate >= DATE_SUB(UTC_TIMESTAMP(), INTERVAL 30 MINUTE) OR (ProcessedAt IS NULL AND LastModifiedDate IS NULL AND ClaimedAt IS NULL AND CreatedDate IS NULL)) ORDER BY COALESCE(ProcessedAt, LastModifiedDate, ClaimedAt, CreatedDate) DESC LIMIT 10",
      "expectStatus": 200,
      "onTimeout": "fail",
      "assertions": [
        {
          "path": "response.body.totalSize",
          "numericEquals": 0
        }
      ]
    }
  ]
}
