{"record":{"id":"8695e0d2495db445","repo":"paperclipai/paperclip","slug":"migrator-producer-identity-mismatch","errorCode":null,"errorMessage":"Migrator producer identity mismatch.","messagePattern":"Migrator producer identity mismatch\\.","errorType":"console","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/cloud-readiness.mjs","lineNumber":29,"sourceCode":"const workflow = \".github/workflows/cloud-migrator-artifacts.yml\";\n\nexport async function migratorPublished(sha, fetchImpl, token) {\n  let pending = false;\n  const failures = [];\n  for (let page = 1; page <= 10; page++) {\n    const response = await fetchImpl(`https://api.github.com/repos/${repository}/actions/workflows/cloud-migrator-artifacts.yml/runs?branch=master&head_sha=${sha}&per_page=100&page=${page}`, {\n      headers: { Accept: \"application/vnd.github+json\", ...(token ? { Authorization: `Bearer ${token}` } : {}) },\n      redirect: \"error\", signal: AbortSignal.timeout(30_000),\n    });\n    if (!response.ok) throw new Error(`Migrator producer lookup failed: HTTP ${response.status}`);\n    const body = await response.json();\n    if (!Array.isArray(body.workflow_runs) || !Number.isSafeInteger(body.total_count) || body.total_count < 0 ||\n        (page === 1 && (body.total_count === 0) !== (body.workflow_runs.length === 0))) throw new Error(\"Invalid migrator producer response.\");\n    if (body.total_count === 0) return false;\n    for (const run of body.workflow_runs) {\n      if (run.head_sha !== sha || run.head_branch !== \"master\" || run.path !== workflow ||\n          run.head_repository?.id !== 1170821064 || run.head_repository.full_name !== repository ||\n          ![\"push\", \"workflow_dispatch\"].includes(run.event)) throw new Error(\"Migrator producer identity mismatch.\");\n      // Publication is immutable. A later failed manual run must not hide a\n      // successful exact-source publisher; the signed bundle is checked next.\n      if (run.status === \"completed\" && run.conclusion === \"success\") return true;\n      if (run.status !== \"completed\") pending = true;\n      else failures.push(`${run.id}: ${run.conclusion}`);\n    }\n    if (page * 100 >= body.total_count) {\n      if (pending) return false;\n      throw new Error(`Migrator producers failed: ${failures.join(\", \")}.`);\n    }\n  }\n  throw new Error(\"Too many migrator producer runs to establish publication.\");\n}\n\nexport function verifyManifestProvenance(bytes, sha, { exec = execFileSync } = {}) {\n  versionFor(sha);\n  const scratch = mkdtempSync(path.join(os.tmpdir(), \"cloud-readiness-attestation-\"));\n  try {","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/scripts/cloud-readiness.mjs#L11-L47","documentation":"Each returned workflow run must match the expected producer identity exactly: same head_sha, head_branch 'master', workflow path cloud-migrator-artifacts.yml, head repository id 1170821064 and full_name paperclipai/paperclip, and event push or workflow_dispatch. Any run failing this check throws immediately — the script refuses to trust runs from forks or other commit sources.","triggerScenarios":"A run in the listing was triggered on the same SHA but from a fork (different head_repository id/name), on a non-master branch, by a different event type (e.g. pull_request), or the workflow file was moved/renamed so run.path differs.","commonSituations":"Running the workflow from a pull_request event in CI; repo was transferred (head_repository.id changed); workflow file renamed in .github/workflows; someone re-ran a run whose head_branch is not master; test fixtures using fabricated run objects.","solutions":["Trigger the migrator workflow via push to master or workflow_dispatch on master for the exact commit SHA.","If the repository was renamed/transferred, update the hardcoded repository name and head_repository id (1170821064) in scripts/cloud-readiness.mjs.","If the workflow file moved, update the `workflow` constant at the top of scripts/cloud-readiness.mjs.","Never bless a run from a fork; run publication from the canonical repository."],"exampleFix":"// before\nrun.path = \".github/workflows/migrator.yml\" // renamed workflow\n// after\n// restore or update: const workflow = \".github/workflows/cloud-migrator-artifacts.yml\";","handlingStrategy":"validation","validationCode":"// ensure the publisher run is the trusted producer\nif (run.head_repository?.full_name !== \"paperclipai/paperclip\" || run.head_branch !== \"master\") {\n  throw new Error(\"Run is not a canonical master push — refusing to treat as publisher.\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  await waitForCloudArtifacts(sha);\n} catch (error) {\n  if (error.message === \"Migrator producer identity mismatch.\") {\n    console.error(\"A non-producer run for this SHA was found; re-publish from paperclipai/paperclip@master.\");\n  } else throw error;\n}","preventionTips":["Only run the migrator publish workflow via push to master or workflow_dispatch","Never rename the workflow file without updating the constant in cloud-readiness.mjs","Keep repository ownership/transfer decisions synced with the hardcoded id/name"],"tags":["github-api","supply-chain","provenance"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}