Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions .github/workflows/claude.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
name: Claude Code

on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
pull_request_review:
types: [submitted]
workflow_dispatch:

permissions: {}

jobs:
authorize:
if: |
github.actor_id == '8973343' && github.triggering_actor == github.actor && github.event.sender.type == 'User' && (
github.event_name == 'workflow_dispatch' ||
contains(github.event.comment.body, '@claude') ||
contains(github.event.review.body, '@claude')
) && (github.event_name != 'workflow_dispatch' || github.ref == format('refs/heads/{0}', github.event.repository.default_branch))
runs-on: ubuntu-latest
timeout-minutes: 2
permissions:
contents: read
outputs:
allowed: ${{ steps.authorize.outputs.allowed }}
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.event.repository.default_branch }}
persist-credentials: false
- name: Authorize actor and source repository
id: authorize
env:
GH_TOKEN: ${{ github.token }}
run: node scripts/authorize-claude.cjs

claude:
needs: authorize
if: needs.authorize.outputs.allowed == 'true'
runs-on: ubuntu-latest
timeout-minutes: 30
# One subscription-backed run at a time; queue approved requests instead of replacing them.
concurrency:
group: claude-framework
queue: max
cancel-in-progress: false
permissions:
contents: read
id-token: write
actions: read
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.event.repository.default_branch }}
persist-credentials: false
- name: Setup Node
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: "22"

- name: Enable pnpm
run: corepack enable

- name: Run Claude Code
uses: anthropics/claude-code-action@1d6de8cb0c237e7c15e9e1bdf973826ebae490cc # v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
base_branch: next
use_commit_signing: true
use_sticky_comment: true
include_comments_by_actor: ${{ github.actor }}
allowed_bots: ""
allowed_non_write_users: ""
show_full_output: false
settings: '{"disableAllHooks":true}'
# The App token is separate from GITHUB_TOKEN; explicitly limit its effective grant.
additional_permissions: |
contents: ${{ github.event_name == 'workflow_dispatch' && 'read' || 'write' }}
pull_requests: ${{ github.event_name == 'workflow_dispatch' && 'read' || 'write' }}
issues: ${{ github.event_name == 'workflow_dispatch' && 'read' || 'write' }}
actions: read
claude_args: |
--max-turns 20
--permission-mode ${{ github.event_name == 'workflow_dispatch' && 'dontAsk' || 'acceptEdits' }}
--allowedTools "${{ github.event_name == 'workflow_dispatch' && 'Bash(gh repo view:*)' || 'Bash(git status:*),Bash(git diff:*),Bash(git log:*),Bash(git show:*),Bash(gh repo view:*),Bash(gh issue view:*),Bash(gh pr view:*),Bash(gh pr diff:*),Bash(gh run view:*),Bash(pnpm install --frozen-lockfile --ignore-scripts),Bash(pnpm exec lefthook run pre-commit),Bash(pnpm exec vitest run:*)' }}"
--disallowedTools "${{ github.event_name == 'workflow_dispatch' && 'Edit,Write,Bash(pnpm:*),Bash(git:*),Bash(gh api:*),Bash(gh pr merge:*),Bash(gh pr review:*),Bash(node:*),Bash(curl:*),Bash(wget:*)' || 'Bash(gh api:*),Bash(gh pr merge:*),Bash(gh pr review:*),Bash(git push:*),Bash(git reset:*),Bash(git rebase:*),Bash(node:*),Bash(curl:*),Bash(wget:*)' }}"
# Manual dispatch validates authentication and GitHub access without changing files.
prompt: ${{ github.event_name == 'workflow_dispatch' && 'Read the repository name and default branch using gh repo view ai-driven-dev/framework --json nameWithOwner,defaultBranchRef. Do not change files, commits, branches, issues, or comments. Report CLAUDE_GITHUB_OK with the repository name and default branch.' || '' }}
3 changes: 2 additions & 1 deletion aidd_docs/memory/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Where the project runs and how it ships: CI/CD, environments, and release.
| `dependabot-auto-merge.yml` | merges dependency PRs that pass |
| `close-finished-milestones.yml` | closes a milestone once its issues are |
| `star-history.yml` | refreshes the README star chart |
| `claude.yml` | trusted `@claude` comments and a manual read-only smoke test; authorization, subscription ownership, limits and operations in [Maintainers](../../docs/MAINTAINERS.md#claude-on-github) |

```mermaid
flowchart LR
Expand All @@ -27,7 +28,7 @@ flowchart LR
Release --> Back["back-merge.yml"]
```

Automatic on a push to `main`. Three workflows also accept a manual run: `promote.yml`, `close-finished-milestones.yml`, `star-history.yml`.
Automatic on a push to `main`. Four workflows also accept a manual run: `promote.yml`, `close-finished-milestones.yml`, `star-history.yml`, `claude.yml`.

## Environments

Expand Down
15 changes: 15 additions & 0 deletions aidd_docs/tasks/challenges/claude-personal-access.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
My confidence level of correctness now: 70%

# Correctness (100%)
- L'accès normal au workflow est réservé à l'identité GitHub numérique `8973343`, vérifiée via le compte authentifié `alexsoyes`. Un autre mainteneur, même avec écriture, ne peut ni invoquer Claude ni relancer une demande d'Alex.
- Le filtre du workflow est doublé d'une vérification du sender, du rerunner et de l'identité retournée par l'API des permissions. Un renommage du compte est accepté ; la réutilisation de son ancien login par un autre compte est refusée.
- Les 12 tests ciblés passent, notamment les cas autre writer, relance par un tiers et usurpation du login. Les protections de forks et les limites d'exécution sont conservées.
- Ce choix correspond au moindre privilège pour un usage personnel financé par Alex. Le dépôt reste communautaire : l'autorisation de lancer son assistant ne remplace pas la revue des contributions par les mainteneurs.

# Deal breakers
- La configuration n'est pas encore activée sur `main` : la PR #1014 nécessite une revue de mainteneur. Le lancement réel de Claude et son test de bout en bout ne sont donc pas validés. Le score concerne cet état incomplet, pas une probabilité de sécurité mesurée.

# Suggestions (enhancements only)
- La restriction du workflow ne garantit pas une garde exclusive du jeton. Les utilisateurs ayant écriture peuvent utiliser les secrets du dépôt via des workflows ; les administrateurs peuvent modifier la configuration. Cette frontière de confiance est [documentée par GitHub](https://docs.github.com/en/actions/reference/security/secure-use#use-secrets-for-sensitive-information).
- Si Alex souhaite aussi contrôler chaque utilisation du secret, un environnement GitHub protégé avec Alex comme reviewer est une option. Il ajoute une approbation par exécution ; les administrateurs du dépôt restent de confiance. Cette protection supplémentaire n'a pas été imposée au parcours actuel.
- L'accès réservé à une personne crée une dépendance à sa disponibilité et à son abonnement. C'est un compromis explicite d'outil personnel, pas un service garanti à la communauté.
30 changes: 30 additions & 0 deletions docs/MAINTAINERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,36 @@ How to operate this repository day to day. This file is the **Maintainer** playb
- **Roadmap.** Priority = the community vote (mechanism in `GOVERNANCE.md`). Accepted items live on board #8 — keep `ROADMAP.md` a pointer, don't maintain a second list.
- **Review PRs.** Approve as CODEOWNERS, then squash-merge (merge policy → [`GOVERNANCE.md`](../GOVERNANCE.md#-code-decisions)).

## Claude on GitHub

Mention `@claude` in an issue comment, PR conversation, inline review comment, or submitted review. Include a bounded task and its expected verification, for example: `@claude fix the parser error described above and run the parser tests`. Review the raw issue/PR content before invoking the agent; community-authored text and imported code can contain prompt injection.

Only Alex’s verified GitHub account, currently `alexsoyes` (numeric ID `8973343`), can invoke this workflow, manually dispatch it or rerun a request. The workflow checks that stable identity, the rerunner and current repository write access before the Claude job can access its secret. A renamed login continues to work; reusing the old login with a different account does not. Membership, `author_association` or another maintainer’s write access grants no invocation rights. Other contributors can ask Alex to relay a reviewed request. Rejected requests appear in the **Authorize actor and source repository** job log, without consuming Claude inference quota.

The write-capable agent accepts issues and open PRs whose source is a feature branch in this repository. It refuses fork PRs, deleted sources, closed PRs, and PRs sourced from `main` or `next`. For an external contribution, review it first and, if appropriate, import the reviewed changes into a repository feature branch before asking Claude to edit them. Fork review with a secret-backed write-capable agent is deliberately unsupported.

Authentication uses the installed official Claude GitHub App and the `CLAUDE_CODE_OAUTH_TOKEN` repository secret. The sponsor's personal Claude subscription pays for inference; this is not community API billing. Every authorized invocation consumes Alex’s personal subscription quota. One Claude job runs at a time, with at most 20 turns and a 30-minute timeout. GitHub queues up to 100 approved jobs; beyond that, runs are cancelled. These controls limit bursts and individual runs, not total daily usage.

The workflow checks out the trusted default branch before authorization; the official action subsequently selects the eligible PR head and restores its protected Claude configuration from the PR base. Repo-defined automatic Claude hooks are disabled. Approved shell commands cover read-only Git/GitHub inspection and specific pnpm installation/check commands; general `gh api`, arbitrary Node execution, merges, approvals, force pushes and history rewriting are not approved. Package-manager checks still execute repository code: inspect changes to scripts, plugins, dependencies and tool configuration before invoking Claude. Tool permissions and prompt sanitization cannot guarantee protection from every injection.

This is an invocation restriction, not exclusive custody of the credential: GitHub repository writers can use repository secrets through workflows, and administrators can change workflow/protection settings. It assumes those people are trusted. If exclusive approval of secret access is required, move the token to a protected GitHub environment with Alex as its required reviewer; every run then needs an additional approval, and repository administrators remain within the trust boundary.

The workflow token is read-only apart from the OIDC permission. Claude receives a separate short-lived, repository-scoped App token with `contents`, `pull_requests` and `issues` write access, plus `actions` read access. No workflow, administration or ruleset-bypass access is requested. Verified commits use GitHub API signing. Agent-generated changes still follow the maintainer review and CI requirements in [Governance](../GOVERNANCE.md#-code-decisions); do not grant Claude a branch-protection bypass. A new push requires reviewers to inspect the updated diff, even when an older approval remains visible.

All direct actions are pinned to full commit SHAs. The selected Claude action also pins its Claude CLI version internally; Dependabot tracks action updates on `next`. Review the upstream action's security changes when updating its pin.

### Verify and operate

1. Integrate `.github/workflows/claude.yml` on the default branch (`main`); GitHub comment events and the App's workflow validation require it there. Maintainer approval remains required.
2. Run `gh workflow run claude.yml --repo ai-driven-dev/framework`. The smoke test requests a **read-only App token**, forbids local edits, and must report `CLAUDE_GITHUB_OK` with the repository and default branch in its run output. A successful local OAuth test alone does not validate GitHub Actions.
3. On a disposable repository feature PR, invoke a bounded change and verify the progress comment, verified commit, changed files and CI. Check that a fork request and an actor without write access stop in the authorization job.
4. To stop new requests, disable **Claude Code** in Actions or run `gh workflow disable claude.yml --repo ai-driven-dev/framework`; also cancel active and queued runs when necessary. Re-enable with `gh workflow enable claude.yml --repo ai-driven-dev/framework`.
5. The subscription token created on 2026-10-13 is valid for one year. Before expiry or when sponsorship changes, generate a replacement with `claude setup-token`, update the GitHub secret through `gh secret set CLAUDE_CODE_OAUTH_TOKEN --repo ai-driven-dev/framework` using its stdin prompt, and rerun the smoke test. Keep any backup outside this repository and revoke obsolete credentials in the sponsor's Claude account. Never paste a token into a comment, workflow, PR body or command argument.

The official action refuses rebases and force pushes; amending an already-published commit must be performed outside this action.

Primary references: [Claude GitHub Actions setup](https://code.claude.com/docs/en/github-actions), [action security and trust model](https://github.com/anthropics/claude-code-action/blob/1d6de8cb0c237e7c15e9e1bdf973826ebae490cc/docs/security.md), [action limitations](https://github.com/anthropics/claude-code-action/blob/1d6de8cb0c237e7c15e9e1bdf973826ebae490cc/docs/faq.md#why-wont-claude-rebase-my-branch), [GitHub secure workflows](https://docs.github.com/en/actions/reference/security/secure-use), [GitHub concurrency](https://docs.github.com/en/actions/how-tos/write-workflows/choose-when-workflows-run/control-workflow-concurrency).

## 📋 Four axes, one board

Each axis answers one question, and only `Status` lives on the board. Routing (`next`/`main`) is not an axis — it derives from the branch prefix ([routing table](../aidd_docs/memory/vcs.md#branches)).
Expand Down
Loading
Loading