# The hardened shape, reduced the same way as vulnerable.yml.
#
# Compare it to vulnerable.yml. Six things changed; each is tagged with the layer
# from ../docs/mitigations.md that it implements, and with whether it is actually
# load-bearing for the injection path.
#
#   [Layer 0 - LOAD-BEARING] the agent writes its output to /tmp, and a later step
#     - outside the model's reach - posts it, taking the target from
#     `github.event.issue.number` rather than from anything the model produced.
#     The agent can be steered into writing anything into that file; it cannot
#     choose where the file goes.
#
#   [Layer 1 - LOAD-BEARING] `gh issue comment` and `gh issue edit` left the
#     agent's `--allowedTools`, so it has no tool that names a different target.
#
#   [Layer 2 - LOAD-BEARING, for the second job only] the job reachable by
#     comment is gated on the commenter's `author_association`, so only
#     OWNER/MEMBER/COLLABORATOR reach it. A named or empty opt-out would not have
#     been enough; see the note in ../docs/mitigations.md.
#
#   [Layer 4 - real but NOT a bound] issue text is no longer interpolated into
#     `prompt`. The agent fetches it with `gh issue view` instead, so untrusted
#     text arrives as tool output rather than in the instruction channel. The
#     model still reads it, so this reduces the chance of compliance without
#     removing the capability.
#
#   [not a layer - general hygiene] `persist-credentials: false` on checkout, so
#     no usable token is left in .git/config. Good practice; not an injection
#     bound, and the fixture is labelled this way because a reader who counts
#     these as mitigations would overestimate the file.
#
#   [NOT a mitigation] the write scope STAYS. `issues: write` is still here and is
#     still correct, because the later step posts the comment. A detector that
#     keys on the permissions block alone cannot tell this file from
#     vulnerable.yml, and that is the false positive this fixture exists to catch.
#     Removing it would break the workflow, not harden it.
#
# Do not deploy this either; it is a fixture, not a template.
name: Issue Agent

on:
  issues:
    types: [opened]
  issue_comment:
    types: [created]

jobs:
  auto-triage:
    if: |
      github.event_name == 'issues' &&
      github.actor != 'github-actions[bot]' &&
      github.event.issue.state != 'closed' &&
      !github.event.issue.pull_request
    runs-on: ubuntu-latest
    permissions:
      contents: read
      issues: write
      id-token: write
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          persist-credentials: false

      - name: Run triage agent
        uses: anthropics/claude-code-action@v1
        with:
          allowed_non_write_users: ${{ github.event.issue.user.login }}
          claude_args: --allowedTools "Read,Write,Glob,Grep,Bash(gh issue view:*),Bash(gh search issues:*),Bash(grep:*),Bash(ls:*)"
          prompt: |
            Triage the issue this run was triggered by. Fetch it yourself with
            `gh issue view`. Write your comment to /tmp/issue-comment.md and the
            labels, one per line, to /tmp/issue-labels.txt.
            Do NOT attempt to invoke `gh issue comment` or `gh issue edit`.

      - name: Post the agent's comment
        if: always()
        env:
          GH_TOKEN: ${{ github.token }}
          ISSUE: ${{ github.event.issue.number }}
          REPO: ${{ github.repository }}
        run: |
          if [ -f /tmp/issue-comment.md ]; then
            gh issue comment "$ISSUE" --repo "$REPO" --body-file /tmp/issue-comment.md
          else
            echo "Agent produced no comment; nothing to post."
          fi

  on-demand:
    if: |
      github.event_name == 'issue_comment' &&
      contains(github.event.comment.body, '@claude') &&
      (github.event.comment.author_association == 'OWNER' ||
       github.event.comment.author_association == 'MEMBER' ||
       github.event.comment.author_association == 'COLLABORATOR')
    runs-on: ubuntu-latest
    permissions:
      contents: read
      issues: write
      id-token: write
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          persist-credentials: false

      - name: Run triage agent
        uses: anthropics/claude-code-action@v1
        with:
          claude_args: --allowedTools "Read,Write,Glob,Grep,Bash(gh issue view:*),Bash(gh search issues:*),Bash(grep:*),Bash(ls:*)"
          prompt: |
            Answer the maintainer's request. Write your comment to
            /tmp/issue-comment.md.

      - name: Post the agent's comment
        if: always()
        env:
          GH_TOKEN: ${{ github.token }}
          ISSUE: ${{ github.event.issue.number }}
          REPO: ${{ github.repository }}
        run: |
          if [ -f /tmp/issue-comment.md ]; then
            gh issue comment "$ISSUE" --repo "$REPO" --body-file /tmp/issue-comment.md
          fi
