diff --git a/.github/CLAUDE_AUTOMATION.md b/.github/CLAUDE_AUTOMATION.md deleted file mode 100644 index e1bcbe3..0000000 --- a/.github/CLAUDE_AUTOMATION.md +++ /dev/null @@ -1,213 +0,0 @@ -# Claude Issue Implementation Automation - -This repository includes GitHub workflow automation that allows Claude to implement issues automatically when requested via issue comments. - -## How to Use - -### 1. Trigger Implementation - -Comment on any open issue with one of these triggers: -- `@claude implement` -- `@claude fix` -- `@claude create` - -**Example:** -``` -@claude implement - -Please add TypeScript support for the billing configuration options. -``` - -### 2. What Happens - -When you trigger the automation: - -1. **Permission Check**: Verifies you have write access to the repository -2. **Branch Creation**: Creates a new branch under `claude/issue-{number}-{timestamp}` -3. **Implementation**: Claude analyzes the issue and implements the requested changes using the official Anthropic Claude Code action -4. **Pull Request**: Automatically creates a PR with the implementation -5. **Notification**: Updates the issue with progress and results - -### 3. Branch Naming Convention - -Branches are created with the pattern: -``` -claude/issue-{issue-number}-{timestamp} -``` - -**Examples:** -- `claude/issue-123-20241218-143052` -- `claude/issue-456-20241218-151234` - -### 4. Requirements - -#### Repository Setup -- The workflow must be merged into your default branch (usually `main` or `dev`) -- Required GitHub secrets: - - `CLAUDE_CODE_OAUTH_TOKEN` - Your Claude Code OAuth token for implementation - -#### Issue Requirements -- Issue must be **open** -- Issue should have clear, actionable requirements -- Include relevant context, code examples, or specifications - -#### User Permissions -- Only users with **write access** or higher can trigger implementations -- This includes repository collaborators, maintainers, and owners - -## Examples - -### Good Issue for Implementation -```markdown -## Feature Request: Add Invoice PDF Export - -**Description**: Users should be able to export invoices as PDF files - -**Requirements**: -- Add "Export PDF" button to invoice detail page -- Generate PDF using existing invoice data -- Include company logo and styling -- Support both individual and bulk export - -**Acceptance Criteria**: -- [ ] PDF export button appears on invoice page -- [ ] Generated PDF matches invoice design -- [ ] Bulk export works from invoice list -- [ ] Error handling for failed exports -``` - -### Trigger Comment -``` -@claude implement - -Please implement the PDF export feature as described in the issue. Make sure to follow the existing code patterns and add appropriate tests. -``` - -## Workflow Features - -### ✅ Automated Branch Management -- Creates unique branches for each implementation -- Cleans up branches if no changes are made -- Prevents branch name conflicts - -### ✅ Permission Control -- Validates user has write access before proceeding -- Provides clear error messages for unauthorized users - -### ✅ Progress Tracking -- Real-time updates in issue comments -- Links to workflow execution logs -- Clear success/failure notifications - -### ✅ Quality Assurance -- Uses official Anthropic Claude Code action -- Follows existing code patterns -- Includes appropriate documentation -- Maintains project coding standards -- Runs build, typecheck, and lint commands - -## Troubleshooting - -### Implementation Failed -If the workflow fails: -1. Check the [Actions tab](../../actions) for detailed logs -2. Verify the issue has clear, actionable requirements -3. Ensure repository permissions are configured correctly -4. Check that `CLAUDE_CODE_OAUTH_TOKEN` secret is set -5. Try again with more specific requirements - -### No Changes Made -If Claude determines no changes are needed: -- The issue might already be implemented -- Requirements may need clarification -- The request might not be actionable as code - -### Permission Denied -If you get permission errors: -- Verify you have write access to the repository -- Contact a repository maintainer for access -- Check if you're commenting on the correct repository - -## Advanced Usage - -### Multiple Implementations -You can request multiple implementations on the same issue: -- Each trigger creates a new branch -- Previous implementations remain available -- Latest implementation gets priority - -### Custom Instructions -Provide specific implementation guidance: -``` -@claude implement - -Use the Stripe API for payment processing. Follow the existing payment provider pattern in src/providers/. Make sure to add proper error handling and webhook support. -``` - -### Review Process -All implementations create pull requests that: -- Reference the original issue -- Include detailed implementation notes -- Require manual review before merging -- Follow standard PR review process - -## Configuration - -### Required Secrets -Add these secrets in repository settings: - -| Secret | Description | Required | -|--------|-------------|----------| -| `CLAUDE_CODE_OAUTH_TOKEN` | Claude Code OAuth token for implementation | Yes | - -### Workflow Permissions -The workflow requires these permissions: -- `contents: write` - Create branches and commits -- `issues: write` - Comment on issues -- `pull-requests: write` - Create pull requests -- `id-token: write` - Required for Claude Code action - -### Allowed Tools -Claude can run these commands during implementation: -- `pnpm build` - Build the project -- `pnpm typecheck` - Run TypeScript type checking -- `pnpm lint` - Run ESLint -- `npm run test` - Run tests - -## Technical Details - -### Claude Code Action -This workflow uses the official `anthropics/claude-code-action@beta` which provides: -- Direct integration with Claude's code generation capabilities -- Secure authentication via OAuth tokens -- Advanced code analysis and implementation features -- Built-in safety and quality controls - -### Implementation Process -1. Claude analyzes the issue requirements -2. Reviews existing codebase patterns -3. Generates implementation following project conventions -4. Runs quality checks (build, typecheck, lint) -5. Creates commits with descriptive messages -6. Opens pull request with detailed description - -## Limitations - -- Only works with open issues -- Requires clear, actionable requirements -- Limited to repository collaborators -- May need manual refinement for complex features -- Cannot handle issues requiring external services or APIs without proper configuration - -## Support - -If you encounter issues with the automation: -1. Check workflow logs in the Actions tab -2. Verify issue requirements are clear and actionable -3. Ensure you have proper repository permissions -4. Verify `CLAUDE_CODE_OAUTH_TOKEN` secret is configured -5. Create a new issue describing the problem - ---- - -**Note**: This automation is powered by Anthropic's Claude Code action and creates production-ready code, but all implementations should be reviewed before merging to ensure they meet your specific requirements and quality standards. \ No newline at end of file diff --git a/.github/CLAUDE_PERMISSIONS.md b/.github/CLAUDE_PERMISSIONS.md new file mode 100644 index 0000000..0f0416f --- /dev/null +++ b/.github/CLAUDE_PERMISSIONS.md @@ -0,0 +1,212 @@ +# Claude Workflow Permissions + +This document explains how to configure user permissions for Claude automation workflows. + +## Current Configuration + +### Issue Implementation Workflow +- **Strategy**: `adminOrPrivileged` - Repository admins OR privileged users +- **Privileged Users**: `bastiaan`, `xtr-dev-team` +- **Access Check**: Validates permissions before any Claude implementation + +### Code Review Workflow +- **Strategy**: `privilegedUsers` - Only users in privileged list +- **Applies to**: Pull request reviews +- **Scope**: PRs created by privileged users only + +## Permission Strategies + +### 1. Privileged Users Only +```javascript +const isAllowed = privilegedUsers.includes(username); +``` +- Most restrictive +- Only specific users can use Claude +- Best for sensitive repositories + +### 2. Admins Only +```javascript +const isAllowed = collaborator.permission === 'admin'; +``` +- Repository administrators only +- Automatic based on GitHub permissions +- Good for small teams + +### 3. Admin OR Privileged (Current) +```javascript +const isAllowed = hasAdminAccess || isPrivilegedUser; +``` +- Repository admins OR users in privileged list +- Flexible access control +- **Currently active strategy** + +### 4. Organization Members with Write Access +```javascript +const isAllowed = isOrgMember && hasWriteAccess; +``` +- Organization members with write/admin permissions +- Good for larger organizations + +### 5. Everyone with Access +```javascript +const isAllowed = hasWriteAccess; +``` +- Any collaborator with write access +- Least restrictive option + +## How to Change Permissions + +### Option A: Edit Privileged Users List +1. Open `.github/workflows/claude-implement-issue.yml` +2. Find the `privilegedUsers` array (line ~32) +3. Add or remove usernames: +```javascript +const privilegedUsers = [ + 'bastiaan', + 'xtr-dev-team', + 'new-user', // Add new users here + 'another-user' +]; +``` + +### Option B: Change Permission Strategy +1. Open `.github/workflows/claude-implement-issue.yml` +2. Find line ~77: `const isAllowed = allowedByAdminOrPrivileged;` +3. Replace with your preferred strategy: +```javascript +// Only privileged users +const isAllowed = allowedByUserList; + +// Only admins +const isAllowed = allowedByAdminAccess; + +// Admin + privileged users (current) +const isAllowed = allowedByAdminOrPrivileged; + +// Organization members with write access +const isAllowed = allowedByOrgAndWrite; +``` + +### Option C: Custom Logic +Add your own permission logic: +```javascript +// Example: Allow specific teams +const allowedTeams = ['core-team', 'senior-devs']; +const userTeams = await github.rest.teams.listForUser({ + org: context.repo.owner, + username: username +}); +const isInAllowedTeam = userTeams.data.some(team => + allowedTeams.includes(team.slug) +); + +const isAllowed = hasAdminAccess || isInAllowedTeam; +``` + +## Code Review Permissions + +The code review workflow uses a simpler approach with GitHub's built-in author associations: + +```yaml +if: | + contains(fromJSON('["bastiaan", "xtr-dev-team"]'), github.event.pull_request.user.login) || + github.event.pull_request.author_association == 'OWNER' || + github.event.pull_request.author_association == 'MEMBER' +``` + +### Author Associations: +- `OWNER` - Repository owner +- `MEMBER` - Organization member +- `COLLABORATOR` - Repository collaborator +- `CONTRIBUTOR` - Has contributed to the repository +- `FIRST_TIME_CONTRIBUTOR` - First-time contributor +- `NONE` - No association + +## Testing Permissions + +### Test Access for a User +1. Create a test issue +2. Have the user comment `@claude implement` +3. Check the workflow logs for permission results + +### Debug Permission Issues +1. Go to **Actions** tab +2. Click on the failed workflow run +3. Expand "Check user permissions" step +4. Review the permission details in logs + +## Error Messages + +### Access Denied +``` +❌ Access Denied: Claude implementation is restricted to privileged users only. + +Your access level: write +Privileged user: No +Organization member: Yes + +Contact a repository administrator for access. +``` + +### Permission Details +The error message shows: +- Current repository permission level +- Whether user is in privileged list +- Organization membership status + +## Security Considerations + +### Best Practices +1. **Start Restrictive**: Begin with privileged users only +2. **Regular Audits**: Review privileged user list regularly +3. **Monitor Usage**: Check workflow logs for unexpected access attempts +4. **Team-based Access**: Consider using GitHub teams for larger organizations + +### Risks +- **Over-permissive**: Too many users can increase costs and misuse +- **Under-permissive**: Blocks legitimate development work +- **Stale Permissions**: Former team members with lingering access + +## Configuration Examples + +### Small Team (2-5 developers) +```javascript +const privilegedUsers = ['owner', 'lead-dev']; +const isAllowed = allowedByAdminOrPrivileged; +``` + +### Medium Team (5-15 developers) +```javascript +const privilegedUsers = ['owner', 'lead-dev', 'senior-dev1', 'senior-dev2']; +const isAllowed = allowedByAdminOrPrivileged; +``` + +### Large Organization +```javascript +// Use organization membership + write access +const isAllowed = allowedByOrgAndWrite; +``` + +### Open Source Project +```javascript +// Only maintainers +const privilegedUsers = ['maintainer1', 'maintainer2']; +const isAllowed = allowedByUserList; +``` + +## Troubleshooting + +### Common Issues +1. **User not in list**: Add username to `privilegedUsers` array +2. **Wrong permission level**: User needs write access minimum +3. **Organization issues**: Verify org membership if using org-based permissions +4. **Case sensitivity**: Usernames are case-sensitive + +### Quick Fixes +- **Add user**: Edit workflow file, add to privileged users +- **Temporary access**: Change strategy to `allowedByAdminAccess` temporarily +- **Emergency access**: Repository admins always have access with `adminOrPrivileged` strategy + +--- + +**Note**: Changes to workflow files require a commit to take effect. Test permissions after any modifications. \ No newline at end of file diff --git a/.github/claude-config.json b/.github/claude-config.json new file mode 100644 index 0000000..41d105f --- /dev/null +++ b/.github/claude-config.json @@ -0,0 +1,23 @@ +{ + "privilegedUsers": [ + "bastiaan", + "xtr-dev-team" + ], + "permissions": { + "issueImplementation": { + "strategy": "adminOrPrivileged", + "description": "Allow admins and privileged users to request Claude implementations" + }, + "codeReview": { + "strategy": "privilegedUsers", + "description": "Only run Claude reviews for privileged users" + } + }, + "strategies": { + "privilegedUsers": "Only users in the privilegedUsers list", + "adminsOnly": "Only repository admins", + "adminOrPrivileged": "Repository admins OR users in privilegedUsers list", + "orgMembersWithWrite": "Organization members with write access", + "everyone": "All users with repository access" + } +} \ No newline at end of file diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml index a12225a..f425f6d 100644 --- a/.github/workflows/claude-code-review.yml +++ b/.github/workflows/claude-code-review.yml @@ -12,11 +12,23 @@ on: jobs: claude-review: - # Optional: Filter by PR author + # Permission filter: Only allow specific users or admins to trigger reviews + if: | + contains(fromJSON('["bastiaan", "xtr-dev-team"]'), github.event.pull_request.user.login) || + github.event.pull_request.author_association == 'OWNER' || + github.event.pull_request.author_association == 'MEMBER' + + # Alternative filters (comment out the above and use one of these): + # Only for external contributors: + # if: github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR' + + # Only for specific users: + # if: contains(fromJSON('["username1", "username2"]'), github.event.pull_request.user.login) + + # Only for non-admins (let admins skip review): # if: | - # github.event.pull_request.user.login == 'external-contributor' || - # github.event.pull_request.user.login == 'new-developer' || - # github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR' + # github.event.pull_request.author_association != 'OWNER' && + # github.event.pull_request.author_association != 'MEMBER' runs-on: ubuntu-latest permissions: diff --git a/.github/workflows/claude-implement-issue.yml b/.github/workflows/claude-implement-issue.yml index 9414a50..ba520d3 100644 --- a/.github/workflows/claude-implement-issue.yml +++ b/.github/workflows/claude-implement-issue.yml @@ -22,27 +22,81 @@ jobs: runs-on: ubuntu-latest steps: - - name: Check if user has write access + - name: Check user permissions uses: actions/github-script@v7 with: script: | + const username = context.actor; + + // Method 1: Specific privileged users list + const privilegedUsers = [ + 'bastiaan', // Repository owner + 'xtr-dev-team', // Core team members + // Add more usernames here + ]; + + // Method 2: Check repository permission level const { data: collaborator } = await github.rest.repos.getCollaboratorPermissionLevel({ owner: context.repo.owner, repo: context.repo.repo, - username: context.actor + username: username }); + // Method 3: Check organization membership (if applicable) + let isOrgMember = false; + try { + await github.rest.orgs.getMembershipForUser({ + org: context.repo.owner, + username: username + }); + isOrgMember = true; + } catch (error) { + // User is not an org member or org doesn't exist + isOrgMember = false; + } + + // Combined permission check + const isPrivilegedUser = privilegedUsers.includes(username); + const hasAdminAccess = collaborator.permission === 'admin'; const hasWriteAccess = ['admin', 'write'].includes(collaborator.permission); - if (!hasWriteAccess) { + + // Choose your permission strategy: + // Option A: Only specific users + const allowedByUserList = isPrivilegedUser; + + // Option B: Only admins + const allowedByAdminAccess = hasAdminAccess; + + // Option C: Admin + specific users + const allowedByAdminOrPrivileged = hasAdminAccess || isPrivilegedUser; + + // Option D: Organization members with write access + const allowedByOrgAndWrite = isOrgMember && hasWriteAccess; + + // Set your chosen strategy here: + const isAllowed = allowedByAdminOrPrivileged; // Change this line to use your preferred strategy + + if (!isAllowed) { + const errorMessage = `❌ **Access Denied**: Claude implementation is restricted to privileged users only. + + **Your access level**: ${collaborator.permission} + **Privileged user**: ${isPrivilegedUser ? 'Yes' : 'No'} + **Organization member**: ${isOrgMember ? 'Yes' : 'No'} + + Contact a repository administrator for access.`; + await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, - body: `❌ Only collaborators with write access can request Claude implementation. Your permission level: ${collaborator.permission}` + body: errorMessage }); - throw new Error('Insufficient permissions'); + throw new Error('Insufficient permissions for Claude implementation'); } + // Log successful access + console.log(`✅ Access granted to ${username} (${collaborator.permission})`); + - name: Checkout repository uses: actions/checkout@v4 with: