Dashboard › publish › Distillation
10118018-f402-468d-b962-e6014d24ed7f["lore_tm_v1_r7tatNL2RvcA46lI7cXJZy0XmZnVUAQXC236cZ486Tc","lore_tm_v1_lPjanXS0OquoodOFvcvnvFyWRgSESM1hIM2N9I_jfbg","lore_tm_v1_T_rKcnLcHgy6Jfak7PudXFPYaXSayrIJghxVkz7uDpA","lore_tm_v1_8AZFAn7C81-JY3qNkfvG2zX8rsrxYfQTDlm08d_YydA","lore_tm_v1_cXQcHypDHSS8ti3vOMoOPVevP0yBYZDAwzsnLgt1uT4","lore_tm_v1_TRub9T-f_OIwgl6W6nVCrL5U9cPV8xfFLK-qVZPHiq0","lore_tm_v1_xbubA1hc1Grg4Y8GVKB4F6RPib-fKCDIk06wFYAbgDI","lore_tm_v1_KrDhVJft5gzTiCYqlKC2WPN3Lfo_0j9ae3Esc6gAlPk","lore_tm_v1_arN3xNbj5ktHiGXsNbJz-hTsW_qh27lm-NwiKEym_98","lore_tm_v1_h40xCWOL_l5i9Xklzw2zWaACQD7p8gYyJcmHTakWt2E","lore_tm_v1_imJPJAY4MkV_JXhuTqZ-92lRK34AhYn-hT4riktqzFc","lore_tm_v1_HZZytzbN9YPmVImFlAH7mcjKFN40p66IBVcUVPjg1Tw","lore_tm_v1_MyFZXOd8HTdlZ8EW1C6VwRs8ViOYG-gwEga8-5sBQk8","lore_tm_v1_BxP8xIL6p-pNdYuA3IGfeu0rqbqhUatbumyAOlhw31c","lore_tm_v1_YWkFEog3R9kqjEFSRAeuP7rIPVkqx7PONGpovoUk0go","lore_tm_v1_SRhacctxwH0gyR6WMom2i8ZmKCggEfALn56Ef-9A5J8","lore_tm_v1_HfATGgzLBf5pCkMsaG1_4Knd_vtahxSLw69066pgNUs","lore_tm_v1_F9Hq-qIGpHc3uxuDmnYevuHaCjEyF3Dqyc1LOjc5LTg","lore_tm_v1_QJBXRBqJZr_1zxdYhV3_IIRPb6v_gjtP1qUWQeAP71o","lore_tm_v1_gtz95HrVhKiei8ugbS1d2cS8JoTdF99xlzg8xXRGas0","lore_tm_v1_w5iSzgNGEWKnBYU-CTC3FWq873y6ughBCj_x0zNz5_I","lore_tm_v1_y-q7VNCDM8rMu5eYUW0BKuRSycAtcHeyggFPSIhc8KA","lore_tm_v1_ivlVw8-s7y37wZtCuOG_laxR98z5ZjTB7Q0vwZrYta8","lore_tm_v1_g1p9FFiMVtd7hmb_RzhpYL4Pt7CAGRIVJahA7BjKwow","lore_tm_v1_lrBYZZG7Q61OqkQ4FEFPAg3fEvcTNjLcYryodqA6iLI","lore_tm_v1_dJGoMzHNuYIHXetB9FUC8UVO01YhOOBYdpx09cxIcCA","lore_tm_v1_0Wry6hhSeIcNRtyEWkzXkI1AGUogkl-jP2omwyUBEK4","lore_tm_v1_cT1SdciYjmaYkEgJCkUf6xbyMdpGkKIKL-deU8xdUuE","lore_tm_v1_L7mX2Mbomm7h66Xb00_PzaoCFxbZ-UdPaXnOElDA6Nw","lore_tm_v1_j-UoJKz7KSPzye7fmPCyW0lGnrdewj5NoDkVXkjSt_k","lore_tm_v1_bQdZIk3RTBd1EFIfHkUehTfN_9G9PATZYnRXHyIQL5E","lore_tm_v1_hiroAD3JuwiFyY2o70CqUxgDF0s-pP47RjMxJNNZGGY","lore_tm_v1_k6PPKRg8DLiwJm-kUiAw46FvBKgAjzNDLmQjy2n8hN0","lore_tm_v1_TGyQF2kmJeaCNwLz2zRfG0uGi0vXRGRhoWXW2Mjt6Wg","lore_tm_v1_JHg6-uBdsHW1BFCDoMIgAjJNjEcTQi4AVpBzZfT6h-A","lore_tm_v1_WUgSAmZN0Ns37Q3ueDngmtB5-dPyu9RydZYfsok6mVQ","lore_tm_v1_aB7Yep3UwQznGmN_DBYcM-zgpUSTXcs5_fKxg9JG9oE","lore_tm_v1_qFkoah5c2ET_3uWNrptt8epPCXRyFs7u0btYFfBkoU8","lore_tm_v1_x0iv6AXjsB_F3UGgIVOfOqSAKMf6-bvsKZc4nf58RT0","lore_tm_v1_Vi0c2wmoEzIA0XXGquhUzAO6asV1qRLpSvlj_AqohIU"]
Date: Aug 27, 2026
src/publish/validate-approval-attestation.js, src/publish/__tests__/authorize-approval.js, src/publish/authorize-approval.js, src/modules/approval-attestation.js, src/modules/approval-authorizer.js, src/modules/__tests__/approval-attestation.js, and src/modules/__tests__/approval-authorizer.js.No files found.src/modules/approval-authorizer.js defines ALLOWED_ROLE_NAMES = new Set(["write", "maintain", "admin"]) and AUTO_APPROVER = "getsantry[bot]". authorizeApproval({ actor, issueTitle, getPermission, autoApprovedRepositories = new Set() }) parses issueTitle using PUBLISH_TITLE_REGEX; malformed titles return { authorized: false, repository: null }; derives repository = getsentry/${title.groups.repo} and releasePath = ${repository}${title.groups.path || ""}; allows getsantry[bot] only for allowlisted releasePath values without calling getPermission; otherwise looks up collaborator permission in owner getsentry and authorizes only allowed roles.Map approval flow against final review findings completed; Implement immutable approval attestation checks in progress; Add adversarial regression coverage pending; Run validation and final reviews pending.src/publish/validate-approval-attestation.js retrieves GitHub issue details, all paginated events, and all paginated comments using APPROVAL_TOKEN and GitHub API version 2026-03-10. validateApprovalAttestation({ attestationAuthor, issueNumber, issueTitle, repository }) requires live issue title equality, a non-null currentAcceptedEvent(events), and hasApprovalAttestation({ attestationAuthor, comments, event, title }). main() requires APPROVAL_TOKEN, APPROVAL_ISSUE_NUMBER, APPROVAL_ISSUE_REPOSITORY, APPROVAL_ISSUE_TITLE, and APPROVAL_ATTESTATION_AUTHOR; it throws The current accepted label has no matching approval attestation when invalid.src/modules/__tests__/approval-attestation.js verifies that the latest accepted event (event ID "200") is matched to an attestation authored by trusted github-actions[bot]; verifies rejection for a mismatched trusted attestation author, stale event ID/title, and malformed <!-- publish-approval not-base64 -->.github-actions[bot] and getsantry[bot], including a successful publish run 31897823685; none was an immutable, event-bound approval attestation.github-actions[bot], bound to the latest accepted event and live issue title, validated before both downstream transitions; planned rejection cleanup under always() using workflow token so failures before app-token setup still remove accepted..github/workflows/publish.yml, .github/workflows/ci-poller.yml, and src/publish/__tests__/authorize-approval.js; added src/publish/__tests__/validate-approval-attestation.js.src/modules/__tests__/approval-attestation.js (2), src/modules/__tests__/approval-authorizer.js (14), src/publish/__tests__/authorize-approval.js (3), and src/publish/__tests__/validate-approval-attestation.js (2).29503999078 for actor getsantry[bot].src/modules/__tests__/approval-attestation.js.accepts numeric event IDs returned by GitHub's issue events API failed: currentAcceptedEvent() returned null instead of { actor: "contractor", eventId: "29503999078" }; 2 of 3 tests passed.src/modules/approval-attestation.js to support GitHub numeric event IDs.accepted after the ci-ready event could leave a matching historical attestation; concluded live validation must additionally require that accepted is currently present on the issue.src/publish/validate-approval-attestation.js and src/publish/__tests__/validate-approval-attestation.js to require live accepted-label presence.src/publish/__tests__/validate-approval-attestation.js passed all 3 tests after adding live-label validation.ci-ready after either the approval attestationβs bound latest accepted-label event or live issue title changes..github/workflows/ci-poller.yml now checks out publish code via actions/checkout@v6 with persist-credentials: false, then invokes node src/publish/validate-approval-attestation.js before moving a release to ci-ready; it supplies APPROVAL_TOKEN="$GH_TOKEN", APPROVAL_ATTESTATION_AUTHOR="github-actions[bot]", issue number, repository, and title. On validation failure it removes ci-pending and accepted, comments Approval is invalid or could not be verified. Re-add the accepted label to retry after resolving the issue., and continues..github/workflows/publish.yml now checks out code with persist-credentials: false; obtains actions/create-github-app-token@v3 release-bot token using SENTRY_RELEASE_BOT_CLIENT_ID, SENTRY_RELEASE_BOT_PRIVATE_KEY, and owner: getsentry; runs node src/publish/authorize-approval.js with issue context; records steps.authorization.outputs.approval_attestation as an issue comment when authorization succeeds; then validates it with node src/publish/validate-approval-attestation.js using github.token and trusted author github-actions[bot]..github/workflows/publish.yml rejects invalid approval under always() if authorization, attestation recording, or attestation validation fails; cleanup removes accepted, posts the invalid-approval retry comment, and exits 1. The publication job checks out into .__publish__ with persist-credentials: false, validates node .__publish__/src/publish/validate-approval-attestation.js before publication, and performs the same always() rejection cleanup on failure.accepted: a prior attestation must be invalid even if title and actor remain unchanged, because the accepted-label event changes.accepted adversarial regression coverage to src/publish/__tests__/validate-approval-attestation.js.src/publish/__tests__/validate-approval-attestation.js passed all 4 tests. Regression coverage includes title mutation, label removal, label re-addition, and GitHub numeric event IDs.src/modules/__tests__/approval-attestation.js, src/modules/approval-attestation.js, src/modules/details-from-context.js, src/publish/__tests__/validate-approval-attestation.js, src/publish/authorize-approval.js, and src/publish/validate-approval-attestation.js..github/workflows/publish.yml, .github/workflows/ci-poller.yml, src/modules/details-from-context.js, approval-attestation/authorizer modules and tests, and publish authorization/validation scripts and tests; subsequent formatting check reported all matched files use Prettier code style.no-unused-vars.vitest run passed 9 test files and 40 tests. ESLint then reported 4 errors: pre-existing .github/workflows/cocoapods-keepalive.yml:1:7 yml/plain-scalar; new-code src/modules/approval-attestation.js:62:7 and :62:30 BigInt is not defined (no-undef); and src/publish/validate-approval-attestation.js:1:7 unused fs (no-unused-vars).fs import and replace unsupported BigInt use with a strict decimal-ID comparator; BigInt was rejected because project ESLint flags it as undefined.src/modules/approval-attestation.js and src/publish/validate-approval-attestation.js to replace BigInt comparison and remove the unused fs import.src/modules/__tests__/approval-attestation.js (3) and src/publish/__tests__/validate-approval-attestation.js (4). ESLint rerun reported only 1 remaining error: pre-existing .github/workflows/cocoapods-keepalive.yml:1:7 yml/plain-scalar..github/workflows/cocoapods-keepalive.yml.Map approval flow against final review findings, Implement immutable approval attestation checks, and Add adversarial regression coverage completed; Run validation and final reviews in progress.vitest run passed 9 files and all 40 tests. Direct ESLint invocation on .github/workflows/ci-poller.yml and .github/workflows/publish.yml produced only ignored-file warnings, not errors. Prettier check passed for all matched files..github/workflows/cocoapods-keepalive.yml.ses_fbb32b75affe6fDLmwvTL8iPpV; task remained running, with instruction not to poll, duplicate its work, or work on overlapping files/topics.