{
  "name": "Claude Config Sync Webhook",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "github-app-installation",
        "responseMode": "responseNode",
        "options": {}
      },
      "id": "webhook-node",
      "name": "GitHub App Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        3264,
        752
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 1
          },
          "conditions": [
            {
              "id": "installation-event",
              "leftValue": "={{ $json.headers['x-github-event'] }}",
              "rightValue": "installation",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            },
            {
              "id": "installation-repositories-event",
              "leftValue": "={{ $json.headers['x-github-event'] }}",
              "rightValue": "installation_repositories",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            },
            {
              "id": "issues-event",
              "leftValue": "={{ $json.headers['x-github-event'] }}",
              "rightValue": "issues",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "or"
        },
        "options": {}
      },
      "id": "filter-events",
      "name": "Filter Events",
      "type": "n8n-nodes-base.filter",
      "typeVersion": 2,
      "position": [
        4160,
        656
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "action-created",
              "leftValue": "={{ $json.body.action }}",
              "rightValue": "created",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            },
            {
              "id": "action-added",
              "leftValue": "={{ $json.body.action }}",
              "rightValue": "added",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            },
            {
              "id": "action-edited-dashboard",
              "leftValue": "={{ $json.body.action === 'edited' && ($json.body.issue?.title || '').includes('Claude Config Sync Dashboard') && ($json.body.issue?.body || '').includes('[x] **Request sync now**') }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "equals"
              }
            }
          ],
          "combinator": "or"
        },
        "options": {}
      },
      "id": "filter-actions",
      "name": "Filter Actions",
      "type": "n8n-nodes-base.filter",
      "typeVersion": 2,
      "position": [
        4384,
        656
      ]
    },
    {
      "parameters": {
        "jsCode": "// Extract target repos based on event type\nconst event = $input.first().json.headers['x-github-event'];\nconst body = $input.first().json.body;\nlet target_repos = '';\n\nif (event === 'installation' && body.action === 'created') {\n  // New installation - repos in body.repositories\n  const repos = body.repositories || [];\n  target_repos = repos.map(r => r.full_name).join(',');\n} else if (event === 'installation_repositories' && body.action === 'added') {\n  // Repos added to installation - repos in body.repositories_added\n  const repos = body.repositories_added || [];\n  target_repos = repos.map(r => r.full_name).join(',');\n} else if (event === 'issues' && body.action === 'edited') {\n  // Dashboard sync request - single repo\n  target_repos = body.repository.full_name;\n}\n\nreturn [{ json: { target_repos, headers: $input.first().json.headers, body } }];"
      },
      "id": "extract-target-repos",
      "name": "Extract Target Repos",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        4608,
        656
      ]
    },
    {
      "parameters": {
        "authentication": "oAuth2",
        "resource": "workflow",
        "owner": {
          "__rl": true,
          "value": "YOUR_GITHUB_USERNAME",
          "mode": "name"
        },
        "repository": {
          "__rl": true,
          "value": "claude-config",
          "mode": "name"
        },
        "workflowId": {
          "__rl": true,
          "mode": "filename",
          "value": "sync-to-repos.yaml"
        },
        "ref": {
          "__rl": true,
          "value": "main",
          "mode": "name"
        },
        "inputs": "={{ JSON.stringify({ target_repos: $json.target_repos }) }}"
      },
      "id": "trigger-workflow",
      "name": "Trigger Workflow Dispatch",
      "type": "n8n-nodes-base.github",
      "typeVersion": 1.1,
      "position": [
        4832,
        656
      ],
      "credentials": {
        "githubOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "respondWith": "noData",
        "options": {
          "responseCode": 200
        }
      },
      "id": "respond-200",
      "name": "Respond 200 OK",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        3936,
        656
      ],
      "typeVersion": 1.4
    },
    {
      "parameters": {
        "respondWith": "noData",
        "options": {
          "responseCode": 401
        }
      },
      "id": "respond-401",
      "name": "Respond 401 Unauthorized",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        3936,
        848
      ],
      "typeVersion": 1.4
    },
    {
      "parameters": {
        "action": "hmac",
        "type": "SHA256",
        "value": "={{ JSON.stringify($json.body) }}",
        "dataPropertyName": "=signature-256",
        "secret": "YOUR_GITHUB_WEBHOOK_SECRET"
      },
      "id": "compute-hmac",
      "name": "Compute HMAC256",
      "type": "n8n-nodes-base.crypto",
      "position": [
        3488,
        752
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "validate-signature",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json['signature-256'] }}",
              "rightValue": "={{ $json.headers['x-hub-signature-256'].split('=').pop() }}"
            }
          ]
        },
        "options": {}
      },
      "id": "validate-hmac",
      "name": "Validate HMAC256",
      "type": "n8n-nodes-base.if",
      "position": [
        3712,
        752
      ],
      "typeVersion": 2.2
    },
    {
      "parameters": {
        "errorMessage": "HMAC256 signature doesn't match provided signature. Make sure that the GitHub webhook secret is identical to the secret stored in the 'Compute HMAC256' node."
      },
      "id": "stop-error",
      "name": "Stop and Error",
      "type": "n8n-nodes-base.stopAndError",
      "position": [
        4160,
        848
      ],
      "typeVersion": 1
    }
  ],
  "connections": {
    "GitHub App Webhook": {
      "main": [
        [
          {
            "node": "Compute HMAC256",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Events": {
      "main": [
        [
          {
            "node": "Filter Actions",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Actions": {
      "main": [
        [
          {
            "node": "Extract Target Repos",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Target Repos": {
      "main": [
        [
          {
            "node": "Trigger Workflow Dispatch",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Trigger Workflow Dispatch": {
      "main": [
        []
      ]
    },
    "Respond 200 OK": {
      "main": [
        [
          {
            "node": "Filter Events",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Compute HMAC256": {
      "main": [
        [
          {
            "node": "Validate HMAC256",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate HMAC256": {
      "main": [
        [
          {
            "node": "Respond 200 OK",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respond 401 Unauthorized",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Respond 401 Unauthorized": {
      "main": [
        [
          {
            "node": "Stop and Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  }
}