# Contract: nomadcode.gito-branch-webhook-consumer.v1 ## 범위 이 계약은 NomadCode Core가 Gito의 signed HTTP `branch.updated` webhook delivery를 수신해 develop checkout fetch/scan 및 roadmap creation sync wakeup으로 넘기는 외부 소비 경계를 정의한다. 원문 제공 계약은 Gito `agent-contract/provided/gito-forgejo-branch-events-v1.md`의 `gito.forgejo-branch-events.v1`이다. 이 문서는 NomadCode가 소비자로서 강제하는 endpoint, headers, enablement, response 의미만 기록한다. ## 비범위 - Forgejo/Git provider webhook을 직접 수신하거나 정규화하는 책임은 Gito에 있다. - Gito event 생성, branch watch, webhook subscription 저장/전송 책임은 Gito에 있다. - IOP model execution port와 Responses API 동작은 NomadCode task execution dependency이며 이 webhook 소비 계약의 schema가 아니다. ## Endpoint ### `POST /api/integrations/gito/webhook` Gito가 delivery하는 `branch.updated` JSON payload를 수신한다. Basic Auth를 우회하는 public callback 경계이며, request body HMAC 서명으로 검증한다. Headers: | Field | Required | Meaning | | --- | --- | --- | | `X-Gito-Event` | 필수 | 고정값 `branch.updated`. 다른 값은 `400`으로 거부한다. | | `X-Gito-Delivery` | 필수 | stable delivery id. HTTP layer idempotency key로 사용한다. | | `X-Gito-Signature` | 필수 | request body에 대한 HMAC-SHA256 hex digest. `sha256=` prefix와 raw hex를 모두 허용한다. | Request body minimum shape: ```json { "type": "branch.updated", "repo_id": "nomadcode", "branch": "develop", "before": "old-sha", "after": "new-sha", "changed_files": [ { "path": "README.md", "change_type": "modified" } ] } ``` Accepted payload rules: | Field | Required | Meaning | | --- | --- | --- | | `type` | 선택 | 있으면 `branch.updated`여야 한다. | | `repo_id` | 필수 | `GITO_REPO_ID`와 같을 때만 처리 대상이다. | | `branch` | 필수 | `GITO_BRANCH` 또는 기본값 `develop`과 같을 때만 처리 대상이다. | | `before` | 선택 | 이전 revision SHA. 내부 bridge로 전달한다. | | `after` | 선택 | 새 revision SHA. 있으면 revision idempotency key에 포함한다. | | `changed_files` | 선택 | 있으면 object list여야 한다. wakeup 힌트이며 source-of-truth로 단정하지 않는다. | Response handling: | Status | Body | Meaning | | --- | --- | --- | | `202` | `{"status":"accepted"}` | 대상 repo/branch event를 처리했다. | | `202` | `{"status":"ignored"}` | repo 또는 branch가 target과 달라 side effect 없이 ack했다. | | `202` | `{"status":"duplicate"}` | 같은 delivery id 또는 같은 `repo_id:branch:after` revision을 이미 처리했다. | | `400` | error object | event type, delivery id, JSON, payload shape가 잘못됐다. | | `401` | error object | signature가 없거나 검증에 실패했다. | | `413` | error object | body가 1 MiB 제한을 넘었다. | | `500` | error object | 내부 handler가 실패했다. 재시도 가능하다. | | `503` | error object | consumer enablement 입력이 준비되지 않았다. | ## Enablement NomadCode Core는 아래 값이 모두 있을 때 Gito HTTP webhook consumer를 wiring한다. | Env | Required | Meaning | | --- | --- | --- | | `GITO_WEBHOOK_SECRET` | 필수 | `X-Gito-Signature` 검증용 signing secret. raw value는 tracked docs에 쓰지 않는다. | | `GITO_REPO_ID` | 필수 | target repo id. | | `GITO_DEVELOP_REPO_PATH` | 필수 | fetch/scan할 develop checkout path. Core container에서 접근 가능해야 한다. | | `ROADMAP_CREATION_TODO_STATE_ID` 또는 `PLANE_TODO_STATE_ID` | 필수 | Plane-origin roadmap creation sync projection 대상 Todo state id. | | `GITO_BRANCH` | 선택 | 기본값 `develop`. | | `GITO_REMOTE_NAME` | 선택 | 기본값 `origin`. | ## Environment Port Profiles 포트 profile은 같은 remote host에서 local용 환경과 dev용 환경을 동시에 분리 운영하기 위한 기본값이다. Endpoint path, headers, body schema는 profile과 무관하게 동일하다. | Profile | NomadCode Core URL | Gito source URL | Preview | DB/cache 후보 | Subscription target | | --- | --- | --- | ---: | ---: | --- | | remote local | `http://127.0.0.1:18010` | `http://127.0.0.1:18060` | `13010` | `15410/16310` | `http://127.0.0.1:18010/api/integrations/gito/webhook` | | remote dev | `http://127.0.0.1:18011` | `http://127.0.0.1:18061` | `13011` | `15411/16311` | `http://127.0.0.1:18011/api/integrations/gito/webhook` | NomadCode Core container 내부 listen은 `8080`을 유지하고 host publish만 `18010` 또는 `18011`로 분리한다. IOP dev model endpoint `http://toki-labs.com:18083/v1`은 NomadCode 실행 dependency이며 이 계약이 소유하는 port가 아니다. ## Consumer Responsibilities - NomadCode는 `branch.updated`를 wakeup signal로만 받아들인다. - NomadCode는 Plane, agent-roadmap, 기타 source-of-truth mutation 전에 target checkout을 fetch/scan해 실제 revision 상태를 재확인한다. - `changed_files`는 relevance 판단 힌트이며 단독 증거가 아니다. - raw webhook secret, token, provider credential, private endpoint 원문은 tracked 문서나 로그에 기록하지 않는다. ## Evidence - `services/core/internal/http/gito_webhook.go` - `services/core/internal/config/config.go` - `services/core/internal/http/router.go` - `services/core/docker-compose.yml` - `services/core/README.md` - `../gito/agent-contract/provided/gito-forgejo-branch-events-v1.md`