Skip to content

ci(claude): mirror harper auth-gate + marker-based edit + script extraction#68

Merged
heskew merged 3 commits intomainfrom
workflow/auth-gate-and-extraction
May 2, 2026
Merged

ci(claude): mirror harper auth-gate + marker-based edit + script extraction#68
heskew merged 3 commits intomainfrom
workflow/auth-gate-and-extraction

Conversation

@heskew
Copy link
Copy Markdown
Member

@heskew heskew commented May 1, 2026

Summary

Brings oauth's claude workflows up to parity with harper after the last calibration sweep. Three harper PRs collapse into one mirror PR here.

Mirrored from What lands
harper#444 Marker-based review-comment edit (<!-- claude-review:v1 -->); Find prior review comment step; log step uses marker filter + updated_at; Bash(gh api:*) + Write added to allowedTools
harper#447 Inline run: | blocks extracted to .github/scripts/ (compose-review-scope, find-prior-review-comment, log-review-to-ai-review-log, parse-claude-mention)
harper#417 Two-job auth gate via HarperFast GitHub App (Members:Read); per-workflow authorize job; CODEOWNERS-derived trust set; auth-gate-invariants.yml validator. Includes the post-review fixes (fail closed on empty USERS_TO_CHECK; validator enforces it).

Adapted for oauth

  • REVIEW_LAYERS keeps repo-type/plugin.
  • ## Repo-specific checks (OAuth plugin) section preserved — CSRF state tokens, redirect URI validation, provider-of-record, session field preservation, path length bounds.
  • claude-mention.yml --allowedTools keeps bun commands (oauth uses both npm and bun).
  • "Do NOT run `bun test`, `npm test`" guidance preserved.
  • oauth's longer mention prompt (Documentation scope boundary, deploying-to-harper-fabric.md skill reference) preserved.
  • oauth's CODEOWNERS already declares @HarperFast/developers and @HarperFast/devops — both are admitted by the auth gate.

Required setup

Org-level secrets are already configured on HarperFast (per harper#417 setup):

  • HARPERFAST_AI_CLIENT_ID
  • HARPERFAST_AI_APP_PRIVATE_KEY

The App is installed with Organization: Members: Read only. No additional setup needed for oauth.

Branch protection followup

After merge, add Auth gate invariants / validate as a required status check on main. Without that, a PR could weaken the auth gate (delete the authorize job, change the if to a tautology, etc.) and still merge. Same pattern as harper.

Test plan

  • Open or push to a PR after this lands → confirm `Claude PR Review / authorize` succeeds and the trust set is logged.
  • `@claude` mention an oauth PR → confirm authorize job admits the commenter and work job runs.
  • Subsequent push on the same PR → confirm the prior review comment is edited in place (same comment ID), and a `@claude` mention response (if any) is untouched.
  • Confirm `auth-gate-invariants / validate` runs on PRs touching `claude-*.yml`.
  • Confirm a "no blockers" run titles correctly (`no blockers`, not `0 finding(s)`).
  • Confirm `$RUNNER_TEMP/claude-review-notes.md` (when written) appears in the log-issue comment but not on the PR.

Followup

  • Branch protection rule on `main` (you).
  • Org-level cross-repo sharing — next-week's piece. After this lands, both harper and oauth have the same shape; that's the artifact we want to package as a reusable workflow / shared scripts repo so harper-pro and future repos don't need to copy this all over again.

🤖 Generated with Claude Code

…action

Brings oauth's claude workflows up to parity with harper after the
last calibration sweep. Three harper PRs collapse here:

- HarperFast/harper#444 (marker-based review-comment edit):
  * Top-level PR comment uses `<!-- claude-review:v1 -->` sentinel
    so subsequent reviews edit the right comment instead of
    clobbering an `@claude` mention response.
  * New `Find prior review comment` step looks up the integer
    database ID of the prior marker'd comment and exposes it as
    `PRIOR_REVIEW_COMMENT_ID` for the agent.
  * Log step also filters by marker; uses `updated_at` for the
    staleness guard since edit-in-place leaves `created_at` frozen.
  * Adds `Bash(gh api:*)` and `Write` to `--allowedTools`.

- HarperFast/harper#447 (script extraction):
  * All inline `run: |` blocks pulled to `.github/scripts/`:
    compose-review-scope, find-prior-review-comment,
    log-review-to-ai-review-log, parse-claude-mention.
  * Workflows invoke via `bash .github/scripts/<name>.sh`.

- HarperFast/harper#417 (two-job auth gate via App-minted org token):
  * New `authorize` job in each claude-*.yml. Mints an installation
    token from the HarperFast `HarperFast AI Workflows` GitHub App
    (Members:Read), checks team membership against the trust set
    derived from `.github/CODEOWNERS`. Single
    `if: needs.authorize.outputs.authorized == 'true'` on the work/
    review job.
  * Script `authorize-claude-workflow.sh` is parameterized via
    USERS_TO_CHECK (newline-separated) + ADMIT_CLAUDE_BOT.
    Per-workflow specifics:
      - claude-review: PR author + event actor (both must pass);
        admits claude[bot] for AI-authored PRs.
      - claude-mention: commenter only; no claude[bot].
      - claude-issue-to-pr: labeler (github.actor); no claude[bot].
  * New `auth-gate-invariants.yml` workflow + script run on PRs
    touching claude-*.yml; validates structural invariants
    (authorize job present, app-token pinned to SHA, no write
    perms on authorize, secrets referenced, USERS_TO_CHECK set,
    needs/if shape on every other job).
  * Includes the post-review fixes from #417 review:
    - Auth script fails closed when USERS_TO_CHECK is empty or
      whitespace-only (loop-skip + trailing echo would otherwise
      authorize empty input).
    - Validator structurally enforces USERS_TO_CHECK presence.

oauth-specific bits preserved as-is:
- REVIEW_LAYERS includes `repo-type/plugin`.
- `## Repo-specific checks (OAuth plugin)` section: CSRF, redirect
  URI, provider-of-record, session field preservation, path length
  bounds.
- claude-mention.yml --allowedTools keeps the bun commands oauth
  uses (npm + bun mixed toolchain).
- Setup Bun step preserved.
- "Do NOT run `bun test`, `npm test`" guidance preserved.
- oauth's longer claude-mention prompt (Documentation scope
  boundary, deploying-to-harper-fabric.md skill reference, etc.)
  preserved.

Required (organization-level) secrets — already configured on the
HarperFast org per harper #417 setup:
  - HARPERFAST_AI_CLIENT_ID
  - HARPERFAST_AI_APP_PRIVATE_KEY

After merge: add `Auth gate invariants / validate` as a required
status check on `main` in branch protection (same pattern as
harper).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@heskew heskew requested a review from a team as a code owner May 1, 2026 22:43
Mirror of HarperFast/harper#452. Same fix applied to the oauth
review workflow: max-turns doubled, turn-budget hint added,
repo-wide search called out as the single biggest turn-burner.

The triggering harper run is referenced as the concrete failure
mode rather than re-running the same diagnosis on oauth (oauth
hasn't seen the same failure yet, but the prompt and budget are
identical, so the same exposure exists).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mirror of HarperFast/harper#453. Same one-line fix.

The validator's USERS_TO_CHECK presence check used jq's `// empty`
keyword, but ubuntu-latest's yq is mikefarah/yq (Go). yq's lexer
rejects `empty`; `2>/dev/null` ate the error; the variable came
back empty; the existence check tripped on every workflow.

Replaces the expression with idiomatic yq:
`.jobs.authorize.steps[].env.USERS_TO_CHECK | select(. != null)`
piped through `head -1`.

Verified locally with mikefarah/yq v4.53.2 against all three
oauth claude-*.yml workflows — all pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@heskew heskew merged commit 5d14401 into main May 2, 2026
7 of 9 checks passed
@heskew heskew deleted the workflow/auth-gate-and-extraction branch May 2, 2026 22:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant