Dashboard › publish › Distillation
97702132-667e-46b2-a81b-e4843b2ebb46["lore_tm_v1_i1Yu-ia9Cen6GwmO956qmSgNXZa3AZpNXJwaXW_m2ZU","lore_tm_v1_xh-oQQJgVaYVIOnv30QKsgVqZIy1vmZ7_dvH1q4ggzc","lore_tm_v1_50nERzxdHb6SaL8fXXgKMxCWB0BG4zzxEee8WDLkjqk","lore_tm_v1_vj6SSHH13MAu3pSF2rHUZOrBzferpb9mY6tv_obbN1Y"]
π΄ (01:08) User stated publish.yml must isolate Craft publish state at $GITHUB_WORKSPACE/.craft-state, outside checked-out __repo__/, and pass it through XDG_STATE_HOME; storing state in the target repository was rejected because target-repository contents could pre-populate or influence state before privileged publishing. State filenames are derived from sanitized owner/repo/version plus the first 12 SHA-1 characters of Craftβs canonical container cwd, keeping partial and multi-target state under the trusted workflowβs control.
π΄ (01:08) User stated failure cleanup in src/publish/update-issue.js must parse inputs only when present, catch malformed JSON and skip target restoration, then always call updateIssue() so accepted is removed. Cleanup must remain runnable after every failure or cancellation stage; making cleanup depend on parsed PUBLISH_ARGS was rejected because parsing can fail before output exists and unconditional JSON parsing can leave stale approval.
π΄ (01:08) User requires every local GitHub Action referenceβincluding checkout, setup-node, cache, and create-github-app-tokenβto be pinned to its complete reviewed 40-character commit SHA, with static contracts retained in workflow-action-pinning.js. Mutable version tags such as actions/checkout@v6 were rejected because secret-bearing workflows could execute changed third-party code without review.
π΄ (01:08) User requires the CI poller to always add the ci-ready label after CI passes, even when the label is already present. An idempotence check that skips relabeling is prohibited because re-adding emits a fresh label event, resolves the waiting-for-CI race, and starts publishing for accepted releases; skipping it can strand releases.
π΄ (01:08) User requires workflow_dispatch wherever operators need manual recovery. For privileged recovery, user chose a no-secret relay protected by a main-only environment plus a successful default-branch workflow_run handoff, rejecting direct secret-bearing dispatch because the dispatcher selects workflow YAML before jobs, guards, or checkout execute. Workflows must be identified by checked-in filename such as ci-poller.yml, not placeholders or numeric IDs.
π΄ (01:08) User requires release authorization and attestations to be bound to the exact live request, trusted actor, and current label-event provenance. Automated approval requires request-bound github-actions[bot] proof before sentry-internal-app[bot] adds accepted; generic app identity is insufficient.
π΄ (01:08) User requires a release never to reach ci-ready if its request changes or its accepted event is replaced. The captured event and request digest must be validated before CI, after CI, while recording CI-ready proof, immediately before adding ci-ready, and before Craft. Repeated live fencing was chosen over one-time initial validation because issue state can change during CI or setup.
π΄ (01:08) User requires privileged GitHub Actions using secrets, write permissions, approvals, or release state to execute only trusted default-branch code. Required controls are immutable action SHAs, secret-bearing jobs behind the protected production environment, no repository secrets exposed to arbitrary-ref dispatches, an unprivileged manual-dispatch relay, successful default-branch execution before privileged processing, approval-state revalidation immediately before transitions such as ci-ready, regression tests for workflow invariants, and full tests plus lint after changes.
π΄ (01:08) User requires publishing and CI workflow boundaries to be treated as security gates. Before applying accepted, moving an issue to ci-ready, or publishing, workflows must validate the live canonical issue, current label events, actor provenance, and matching attestations, rejecting renamed, closed, changed, re-approved, self-approved, or unverifiable requests.
π΄ (01:08) User stated the CI poller is solely responsible for adding ci-ready. Recovery must retain workflow_dispatch without executing arbitrary dispatched-ref code or exposing repository secrets; recovery must check out a trusted ref and use protected environments.
π΄ (01:08) User requires least-privilege permissions, no exposure of RBAC data, immutable revisions or digests for actions and publishing images, and regression tests covering ordering and final revalidation immediately before credential-bearing publication.
π΄ (01:08) User requires fail-closed, request-bound release authorization with strict separation between human and automated authorization. Human approvers must currently have GitHub repository permission at write, maintain, or admin level and may not self-approve.
π΄ (01:08) User requires automated bot requests never to authorize through collaborator permissions or by trusting the Internal App label actor alone. Authorization requires the exact parsed repository/release path in auto-approve-repos.txt plus a trusted attestation bound to the live request.
π΄ (01:08) User requires revalidation of the issueβs open state, title, requester, current accepted-label actor/event, and relevant attestations before authorization or publishing. Malformed, missing, stale, mismatched, or changed state must be treated as unauthorized and fail closed.
π΄ (01:08) [enforced-workflow] User requires following the established git workflow of branch creation, pull request, and review; the supplied repository knowledge describes this behavioral pattern across 3 sessions.
π΄ (01:08) User-provided /home/byk/Code/getsentry/publish/package.json identifies package publish as private, version 0.0.1, description "Approval-based publishing system for Sentry", main index.js, repository git@github.com:getsentry/publish.git, author Sentry Open Source <oss@sentry.io>, and license Apache-2.0.
π΄ (01:08) User-provided package.json Volta configuration pins Node.js 24.0.0 and Yarn 1.22.22; its resolutions pins undici to ^6.23.0.
π΄ (01:08) User-provided package.json scripts are "test": "vitest run", "test:watch": "vitest", "lint": "eslint src .github --ignore-pattern '!.github'", and "prettier": "prettier --write src".
π΄ (01:08) User-provided package.json dev dependencies are eslint: ^8.9.0, eslint-config-prettier: ^8.3.0, eslint-plugin-yml: ^0.13.0, prettier: ^2.2.1, and vitest: ^4.1.0; runtime dependencies are @actions/core: ^2.0.0, @actions/github: ^7.0.0, and @sentry/node: ^10.0.0.
π΄ (01:08) User-provided test run used yarn run v1.22.22 and vitest run --printConsoleTrace, executing Vitest v4.0.17 in /home/byk/Code/getsentry/publish; all 16 test files and all 85 tests passed.
π΄ (01:08) User-provided passing test-file results were: src/modules/__tests__/post-workflow-details.jsβ1 test, 13ms; src/publish/__tests__/current-accepted-event.jsβ2 tests, 40ms; src/publish/__tests__/validate-approval-attestation.jsβ9 tests, 54ms; src/modules/__tests__/approval-attestation.jsβ5 tests, 22ms; src/modules/__tests__/update-issue.jsβ6 tests, 13ms; src/modules/__tests__/process-end-state.jsβ4 tests, 80ms; src/publish/__tests__/authorize-approval.jsβ7 tests, 42ms; src/modules/__tests__/approval-authorizer.jsβ15 tests, 21ms.
π΄ (01:08) User-provided remaining passing test-file results were: src/publish/__tests__/record-ci-ready-attestation.jsβ3 tests, 19ms; src/publish/__tests__/ci-poller-workflow.jsβ3 tests, 15ms; src/publish/__tests__/record-auto-approval-attestation.jsβ2 tests, 13ms; src/publish/__tests__/workflow-action-pinning.jsβ16 tests, 8ms; src/modules/__tests__/details-from-context.jsβ5 tests, 9ms; src/libs/__tests__/github.jsβ2 tests, 5ms; src/publish/__tests__/auto-approval-workflow.jsβ3 tests, 4ms; src/publish/__tests__/publish-workflow.jsβ2 tests, 4ms.
π΄ (01:08) User-provided test timing was start 01:08:22, Vitest duration 2.46s with transform 262ms, setup 0ms, import 1.42s, tests 363ms, and environment 6ms; Yarn completed in 3.03s.
π΄ (01:08) User-provided lint run used Yarn 1.22.22 and command eslint src .github --ignore-pattern '!.github'; it completed successfully in 1.11s.