diff --git a/README.md b/README.md index 046669d..42591fb 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,16 @@ # Gito Gito는 agent-driven development를 위한 platformless Git control plane이다. -여러 Git repository를 등록하고, workspace lease, Git operation, provider -adapter, normalized event를 하나의 제어 흐름으로 묶는다. Agent interaction -UI는 sibling `../agent-shell` Flutter package를 사용하고, 그 UI를 구동하는 -backend/runtime은 sibling `../iop` 프로젝트가 맡는 방향으로 둔다. +여러 Git platform의 공통 인터페이스를 제공해 repository registry, +workspace lease, Git operation, provider adapter, normalized event를 하나의 +제어 흐름으로 묶는다. Agent interaction UI는 sibling `../agent-shell` +Flutter package를 사용하고, 그 UI를 구동하는 backend/runtime은 sibling +`../iop` 프로젝트가 맡는 방향으로 둔다. Git 자체 작업은 GitHub/GitLab/Gitea 같은 플랫폼을 몰라도 동작해야 한다. PR/MR, review, checks, webhook 같은 플랫폼 기능은 provider adapter 뒤에 둔다. +외부 연동은 GitHub webhook과 유사한 HTTP webhook/callback 모델을 기본으로 +하고, Gito 전용 binary transport를 요구하지 않는다. ## 현재 상태 @@ -18,7 +21,7 @@ Flutter client는 control surface 경계만 잡혀 있다. - Go `server`, `worker` command build - health/readiness REST placeholder -- proto-socket registry와 binary `event.subscribe` / `branch.updated` event path +- 내부 proto-socket registry와 binary `event.subscribe` / `branch.updated` event path - Forgejo push callback, watched branch listener, branch event smoke/debug surface - PostgreSQL-backed repo, workspace lease, operation, event, branch watch, revision cursor, provider delivery baseline - platformless `gitengine` 최소 테스트 @@ -29,11 +32,12 @@ Flutter client는 control surface 경계만 잡혀 있다. 아직 구현 전인 범위: -- `event` 외 proto-socket channel/action의 실제 command behavior +- `event` 외 내부 proto-socket channel/action의 실제 command behavior - `agent_shell: path: ../agent-shell` package를 쓰는 Flutter host integration - `../iop` backend/runtime 결과를 Gito operation/event 계약으로 수렴시키는 연결 +- 외부 consumer용 HTTP webhook delivery registration과 retry/outbox dispatch - GitHub/GitLab/Gitea provider adapter와 Forgejo PR/MR adapter - Flutter 화면 구성과 operation event 구독 @@ -81,7 +85,7 @@ curl http://127.0.0.1:8080/readyz | --- | --- | | `services/core/cmd/server/` | control plane server entrypoint | | `services/core/cmd/worker/` | operation worker entrypoint | -| `services/core/internal/controlplane/` | REST/proto-socket surface, auth/policy gate 후보 | +| `services/core/internal/controlplane/` | REST API/webhook surface, internal proto-socket surface, auth/policy gate 후보 | | `services/core/internal/core/` | provider-neutral domain model | | `services/core/internal/gitengine/` | platformless Git operation layer | | `services/core/internal/worker/` | operation 실행 orchestration 후보 | @@ -90,7 +94,7 @@ curl http://127.0.0.1:8080/readyz | `services/core/internal/storage/` | PostgreSQL store boundary | | `services/core/migrations/` | database schema migration | | `apps/client/` | Flutter control surface scaffold | -| `packages/contracts/` | proto-socket, REST, event, DTO contract notes | +| `packages/contracts/` | HTTP webhook/REST, internal proto-socket, event, DTO contract notes | | `docs/` | 사람용 architecture/operation 문서 | | `agent-ops/` | agent rules, skills, roadmap helper | | `agent-test/` | local validation rules | @@ -125,12 +129,17 @@ Provider Adapters event 원장으로 수렴한다. - `gitengine`은 platformless여야 하며 local bare repo만으로 테스트 가능해야 한다. - `provider`는 PR/MR/review/checks/webhook 같은 플랫폼 기능만 맡는다. +- 외부 시스템은 GitHub webhook과 비슷한 HTTP webhook/callback으로 연결한다. +- proto-socket은 내부 control/runtime surface로만 사용하고, 외부 연결 규약이나 + 보조 transport로 제공하지 않는다. - PostgreSQL은 source of truth이고, Redis는 필요할 때 fanout/stream 가속 계층으로만 둔다. ## 통신 정책 -- 내부 runtime 통신은 proto-socket을 우선한다. -- REST는 health/readiness, provider callback, smoke/curl, 단순 bootstrap에만 둔다. +- 외부 provider와 consumer 연동은 REST API와 HTTP webhook/callback을 사용한다. +- proto-socket은 내부 control/runtime 통신에만 사용한다. +- REST는 health/readiness, provider callback, external webhook delivery, + smoke/curl, 단순 bootstrap에 둔다. - gRPC는 초기 설계에서 제외한다. - webhook은 빠른 wakeup signal로만 보고, 최종 판정은 Git revision/diff 또는 provider read API로 재검증한다. diff --git a/agent-contract/index.md b/agent-contract/index.md index 4568598..0eca7bb 100644 --- a/agent-contract/index.md +++ b/agent-contract/index.md @@ -8,7 +8,7 @@ | id | 읽는 조건 | path | | --- | --- | --- | -| `gito.forgejo-branch-events.v1` | Forgejo webhook, `branch.updated`, `event.subscribe`, proto-socket event stream, nomadcode branch event wakeup, `/callbacks/forgejo/push`, `/api/listeners/branches` | `agent-contract/provided/gito-forgejo-branch-events-v1.md` | +| `gito.forgejo-branch-events.v1` | Forgejo webhook, `branch.updated`, outbound HTTP webhook delivery, nomadcode branch event wakeup, `/callbacks/forgejo/push`, `/api/listeners/branches`, `/api/webhook-subscriptions` | `agent-contract/provided/gito-forgejo-branch-events-v1.md` | ## 소비 계약 diff --git a/agent-contract/provided/gito-forgejo-branch-events-v1.md b/agent-contract/provided/gito-forgejo-branch-events-v1.md index 9f3be76..df7e926 100644 --- a/agent-contract/provided/gito-forgejo-branch-events-v1.md +++ b/agent-contract/provided/gito-forgejo-branch-events-v1.md @@ -2,13 +2,14 @@ ## 범위 -이 계약은 Gito가 Forgejo push webhook을 받아 watched branch revision 변화로 정규화하고, NomadCode 같은 내부 소비자가 proto-socket event stream으로 수신하는 MVP 경계를 정의한다. +이 계약은 Gito가 Forgejo push webhook을 받아 watched branch revision 변화로 정규화하고, NomadCode 같은 외부/인접 소비자에게 HTTP webhook delivery로 전달하는 경계를 정의한다. Gito는 여러 Git 플랫폼의 공통 control plane을 지향하므로 외부 소비자에게 Gito 전용 binary transport 구현을 요구하지 않는다. ## Transport - Forgejo -> Gito: REST webhook callback. -- Gito -> NomadCode/internal consumers: proto-socket `event` channel. -- REST는 provider callback과 bootstrap/smoke 표면에만 사용한다. +- Gito -> registered consumers: signed HTTP webhook delivery. +- REST는 provider callback, external webhook delivery, bootstrap/smoke 표면에 사용한다. +- proto-socket은 Gito 내부 control/runtime transport이며 이 외부 계약의 일부가 아니다. - gRPC는 이 계약 범위가 아니다. ## REST Callback @@ -94,7 +95,7 @@ Duplicate delivery response (additive field, only present when `true`): } ``` -Idempotency: when a durable store is configured, Gito deduplicates push deliveries by `X-Forgejo-Delivery` header (dedupe key `delivery:`) or by `revision::::` when the header is absent. A duplicate delivery returns the same `accepted=true, matched=true` response with an additional `duplicate=true` field and does not emit a new event or proto-socket broadcast. +Idempotency: when a durable store is configured, Gito deduplicates push deliveries by `X-Forgejo-Delivery` header (dedupe key `delivery:`) or by `revision::::` when the header is absent. A duplicate delivery returns the same `accepted=true, matched=true` response with an additional `duplicate=true` field and does not create a new event or outbound webhook delivery. Status: @@ -140,6 +141,47 @@ Response: Lists active in-memory branch watches. +## Webhook Subscription Bootstrap + +This is the target external subscription surface for the outbound webhook +delivery Milestone. The current MVP may still expose only listener and event +inspection helpers until that Milestone is implemented. + +### `POST /api/webhook-subscriptions` + +Registers an HTTP endpoint that receives normalized Gito events. + +Request: + +```json +{ + "name": "nomadcode-develop-wakeup", + "target_url": "https://consumer.example.invalid/gito/events", + "events": ["branch.updated"], + "repo_id": "nomadcode", + "branch": "develop", + "secret_ref": "secret://gito/webhooks/nomadcode" +} +``` + +Response: + +```json +{ + "subscription": { + "id": "webhook-sub-nomadcode-develop", + "name": "nomadcode-develop-wakeup", + "events": ["branch.updated"], + "repo_id": "nomadcode", + "branch": "develop", + "created_at": "2026-06-13T00:00:00Z" + } +} +``` + +`target_url` and `secret_ref` are examples only. Raw signing secrets, tokens, or +private endpoint values must not be stored in tracked docs. + ## Event Inspection ### `GET /api/events` @@ -175,30 +217,57 @@ Response: } ``` -## Wire Format +## HTTP Webhook Delivery -`/proto-socket` endpoint는 WebSocket 위에서 binary protobuf framing을 사용한다. JSON over WebSocket text frame은 지원하지 않는다. +Gito delivers matched `branch.updated` events to registered HTTP endpoints with a +GitHub-style webhook model. The delivery body is JSON. -- **Frame type**: WebSocket binary frame으로 전송되는 protobuf `PacketBase` 메시지. -- **Payload type**: `PacketBase` 안의 application payload는 `google.protobuf.Struct`로 고정한다. -- **Envelope**: `google.protobuf.Struct`를 역직렬화하면 아래 Envelope 구조를 얻는다. -- **JSON 예시**: 이 문서의 모든 JSON 예시는 Envelope의 논리 표현이다. 실제 wire는 binary protobuf 경로를 사용한다. +Headers: -### Envelope 필드 - -| 필드 | 타입 | 의미 | +| Field | Required | Meaning | | --- | --- | --- | -| `protocol_version` | string | 고정값 `nomadcode.proto-socket.v1` | -| `id` | string | 메시지 식별자 | -| `correlation_id` | string | 요청에 대한 응답일 때 원본 `id` | -| `type` | string | `request`, `response`, `event`, `error` 중 하나 | -| `channel` | string | 채널 이름 (예: `event`) | -| `action` | string | action 이름 (예: `event.subscribe`, `branch.updated`) | -| `payload` | object | action별 payload. 아래 Base Schema 참고 | -| `meta` | object | 진단/라우팅 메타. consumer가 의존하지 않는다. | -| `error` | object | `type=error`일 때만 있음 (`code`, `message`, `retryable`) | +| `X-Gito-Event` | 필수 | Normalized event type, for example `branch.updated`. | +| `X-Gito-Delivery` | 필수 | Stable delivery id. Consumers use this for idempotency. | +| `X-Gito-Signature` | `secret_ref` 설정 시 필수 | HMAC-SHA256 digest over the request body. `sha256=` prefix is allowed. | -### Base Schema 및 Extension 경계 +Request body: + +```json +{ + "id": "event-id", + "type": "branch.updated", + "provider": "forgejo", + "delivery_id": "forgejo-delivery-id", + "repo_id": "nomadcode", + "branch": "develop", + "before": "old-sha", + "after": "new-sha", + "changed_files": [ + { + "path": "README.md", + "change_type": "modified" + } + ], + "observed_at": "2026-06-13T00:00:00Z", + "created_at": "2026-06-13T00:00:00Z" +} +``` + +Delivery response handling: + +| Status | Meaning | +| --- | --- | +| `2xx` | Delivery accepted. | +| `400` | Consumer rejected malformed payload; retry is not useful unless config changed. | +| `401` or `403` | Signature/auth failure; disable or pause delivery until config is fixed. | +| `404` or `410` | Endpoint no longer exists; delivery should be disabled or marked failed. | +| `429` or `5xx` | Retry with backoff. | + +Delivery idempotency is consumer-visible through `X-Gito-Delivery`. Gito records +attempt state in the durable outbox/delivery store and must not treat webhook +delivery success as proof that the consumer has applied source-of-truth changes. + +## Base Schema 및 Extension 경계 `branch.updated` base payload 필드: @@ -218,80 +287,6 @@ Response: 위 필드는 모두 consumer-neutral한 범용 Git event 정보다. NomadCode 전용 필수 필드는 base payload에 포함하지 않는다. consumer-specific 확장이 필요하면 optional `payload.metadata` 또는 별도 optional field로만 허용한다. -## proto-socket Consumption - -Consumer는 Gito의 `/proto-socket` endpoint에 binary proto-socket 클라이언트로 연결하고 `event.subscribe` request를 보낸다. Gito는 요청을 수락하고 연결별로 subscription을 저장한다. 감시 중인 branch event는 `action`, `repo_id`, `branch`가 일치하는 구독 연결에만 broadcast한다. - -아래 JSON 예시는 논리 envelope 표현이다. wire는 binary protobuf frame을 사용한다. - -Subscribe request: - -```json -{ - "protocol_version": "nomadcode.proto-socket.v1", - "id": "msg-1", - "type": "request", - "channel": "event", - "action": "event.subscribe", - "payload": { - "events": ["branch.updated"], - "repo_id": "nomadcode", - "branch": "develop" - } -} -``` - -Subscribe response: - -```json -{ - "protocol_version": "nomadcode.proto-socket.v1", - "id": "response-id", - "correlation_id": "msg-1", - "type": "response", - "channel": "event", - "action": "event.subscribe", - "payload": { - "status": "subscribed", - "subscription": { - "events": ["branch.updated"], - "repo_id": "nomadcode", - "branch": "develop" - } - } -} -``` - -Broadcast event: - -```json -{ - "protocol_version": "nomadcode.proto-socket.v1", - "id": "event-id", - "type": "event", - "channel": "event", - "action": "branch.updated", - "payload": { - "id": "event-id", - "type": "branch.updated", - "provider": "forgejo", - "delivery_id": "delivery-id", - "repo_id": "nomadcode", - "branch": "develop", - "before": "old-sha", - "after": "new-sha", - "changed_files": [ - { - "path": "agent-roadmap/phase/example/milestones/example.md", - "change_type": "modified" - } - ], - "observed_at": "2026-06-13T00:00:00Z", - "created_at": "2026-06-13T00:00:00Z" - } -} -``` - ## Field Semantics | Field | Meaning | @@ -315,16 +310,16 @@ Broadcast event: ## Consumer Interop Procedure -NomadCode 또는 다른 consumer가 Gito proto-socket event stream을 연동할 때 따르는 최소 절차다. +NomadCode 또는 다른 consumer가 Gito branch event webhook delivery를 연동할 때 따르는 최소 절차다. 1. `POST /api/listeners/branches`로 watched branch를 등록한다. branch watch가 없으면 이벤트가 발행되지 않는다. -2. `/proto-socket` WebSocket에 binary proto-socket 클라이언트로 연결한다. -3. `event.subscribe` request를 보내 `branch.updated` event와 `repo_id`, `branch` filter를 등록한다. -4. Gito는 Forgejo push webhook 수신 후 matched branch에 대해 `branch.updated` event를 broadcast한다. +2. Consumer는 HTTP endpoint와 event/repo/branch filter를 Gito webhook subscription으로 등록한다. +3. Gito는 Forgejo push webhook 수신 후 matched branch에 대해 durable `branch.updated` event를 기록한다. +4. Gito는 matching subscription의 `target_url`로 signed HTTP POST delivery를 보낸다. 5. Consumer는 base payload(`repo_id`, `branch`, `before`, `after`, `changed_files`)를 자기 내부 wakeup 로직에 매핑한다. -6. 중요 동작 전에 `before`/`after` SHA와 `changed_files`를 참고하되, provider file list를 유일한 상태 증거로 쓰지 않는다. +6. 중요 동작 전에 `before`/`after` SHA와 `changed_files`를 참고하되, provider file list나 webhook delivery를 유일한 상태 증거로 쓰지 않는다. -**NomadCode interop 확인 기준**: NomadCode dev consumer가 generic `branch.updated`를 수신해 내부 wakeup으로 매핑한다. base payload에 NomadCode 전용 필수 필드가 없다. 다른 consumer도 같은 schema를 재사용할 수 있다. +**NomadCode interop 확인 기준**: NomadCode dev consumer가 generic `branch.updated` HTTP webhook delivery를 수신해 내부 wakeup으로 매핑한다. base payload에 NomadCode 전용 필수 필드가 없다. 다른 consumer도 같은 schema를 재사용할 수 있다. ## Provider Responsibilities @@ -335,14 +330,13 @@ NomadCode 또는 다른 consumer가 Gito proto-socket event stream을 연동할 ## 운영 확인 절차 -listener bootstrap, `/proto-socket`, `/api/listeners/branches`, `/api/events`를 secret 없이 재현 가능하게 확인하는 절차다. +listener bootstrap, webhook subscription, `/api/listeners/branches`, `/api/events`를 secret 없이 재현 가능하게 확인하는 절차다. ### 필요한 환경 변수 | 변수 | 필수 | 기본값 | 설명 | | --- | --- | --- | --- | | `APP_ENV` | 아니오 | `development` | 앱 환경 | -| `PROTO_SOCKET_PATH` | 아니오 | `/proto-socket` | proto-socket WebSocket 경로 | | `FORGEJO_WEBHOOK_SECRET` | 아니오 | (없으면 서명 검증 생략) | Forgejo webhook 서명 키 | | `DATABASE_URL` | 아니오 | (없으면 in-memory) | PostgreSQL DSN | @@ -364,20 +358,25 @@ curl -s -X POST http://localhost:8080/api/listeners/branches \ curl -s http://localhost:8080/api/listeners/branches ``` -### Step 3 — proto-socket 레지스트리 확인 +### Step 3 — webhook subscription 등록 ```bash -curl -s http://localhost:8080/proto-socket +curl -s -X POST http://localhost:8080/api/webhook-subscriptions \ + -H "Content-Type: application/json" \ + -d '{"name":"nomadcode-develop-wakeup","target_url":"https://consumer.example.invalid/gito/events","events":["branch.updated"],"repo_id":"nomadcode","branch":"develop","secret_ref":"secret://gito/webhooks/nomadcode"}' ``` -기대 응답: `event` 채널의 `subscribe` action이 `mvp` 상태로 포함된다. +기대 응답: `201 Created`, `{"subscription": {...}}` +이 endpoint는 outbound webhook delivery 구현 Milestone에서 추가한다. -### Step 4 — Binary proto-socket 통합 테스트로 연결 확인 +### Step 4 — webhook delivery worker 통합 테스트로 연결 확인 ```bash -cd services/core && go test -run TestBinaryProtoSocketBranchUpdated ./internal/controlplane/ -v -count=1 +cd services/core && go test -run TestWebhookDeliveryBranchUpdated ./internal/controlplane/ -v -count=1 ``` +이 테스트는 outbound webhook delivery 구현 Milestone에서 추가한다. + ### Step 5 — Forgejo push 트리거 (서명 없는 경우) ```bash @@ -402,4 +401,5 @@ curl -s http://localhost:8080/api/events - Raw webhook secret, token, password, or credential value must not appear in tracked docs, event payloads, logs, or contract examples. - Provider webhook callbacks must not directly mutate NomadCode or Plane state. -- Internal Gito -> NomadCode branch event delivery must not use REST polling as the primary path once proto-socket is available. +- Gito -> external consumer branch event delivery must not require proto-socket. +- Consumer webhook delivery must not be treated as final source-of-truth state. diff --git a/agent-ops/rules/project/domain/contracts/rules.md b/agent-ops/rules/project/domain/contracts/rules.md index ba9cdda..ef9087a 100644 --- a/agent-ops/rules/project/domain/contracts/rules.md +++ b/agent-ops/rules/project/domain/contracts/rules.md @@ -7,8 +7,10 @@ The contracts domain covers `packages/contracts`. ## Rules - Record transport-independent DTOs before binding them to one transport. -- proto-socket is the first internal transport target. -- REST exceptions must be documented. +- External provider and consumer integrations use REST APIs and HTTP + webhook/callback delivery. +- proto-socket is internal-only and must not be documented as an external + integration contract or fallback transport. +- REST exceptions and internal-only transports must be documented. - gRPC is out of scope until explicitly added. - Contract notes must not include raw secrets or private credentials. - diff --git a/agent-roadmap/ROADMAP.md b/agent-roadmap/ROADMAP.md index b144f32..efcc4c8 100644 --- a/agent-roadmap/ROADMAP.md +++ b/agent-roadmap/ROADMAP.md @@ -2,7 +2,7 @@ ## 전체 목표 -Gito는 GitHub, GitLab, Gitea 같은 플랫폼에 묶이지 않는 Git control plane을 제공한다. 여러 repository를 등록하고, workspace lease, Git operation, agent-shell/IOP 실행, provider adapter, normalized event를 하나의 운영 루프로 묶어 agent-driven development를 안전하게 실행할 수 있게 만든다. +Gito는 GitHub, GitLab, Gitea 같은 플랫폼에 묶이지 않는 Git control plane을 제공한다. 여러 Git 플랫폼의 공통 인터페이스로 repository를 등록하고, workspace lease, Git operation, agent-shell/IOP 실행, provider adapter, normalized event를 하나의 운영 루프로 묶어 agent-driven development를 안전하게 실행할 수 있게 만든다. 외부 연동은 GitHub webhook과 비슷한 HTTP webhook/callback 모델을 기본으로 하며, proto-socket은 내부 control/runtime 규약으로만 사용한다. ## Phase 흐름 @@ -13,13 +13,13 @@ Gito는 GitHub, GitLab, Gitea 같은 플랫폼에 묶이지 않는 Git control p - [진행중] Control Plane Foundation - 경로: `agent-roadmap/phase/control-plane-foundation/PHASE.md` - - 요약: platformless Git control plane의 모듈 경계, repo/workspace/operation/event 원장, proto-socket 우선 transport 기준을 build 가능한 baseline으로 닫는다. + - 요약: platformless Git control plane의 모듈 경계, repo/workspace/operation/event 원장, 외부 HTTP webhook/REST와 내부 proto-socket 경계를 build 가능한 baseline으로 닫는다. - [진행중] Agent Shell IOP Execution - 경로: `agent-roadmap/phase/agent-shell-iop-execution/PHASE.md` - 요약: `../agent-shell`은 Flutter agent UI/package로 사용하고, backend/runtime owner는 `../iop`로 지정해 Gito Git control plane과 연결한다. - [계획] Provider Change Request Integration - 경로: `agent-roadmap/phase/provider-change-request-integration/PHASE.md` - - 요약: GitHub PR, GitLab MR, Gitea PR 같은 provider 기능을 ChangeRequest 추상화와 adapter 구조로 통합한다. + - 요약: GitHub PR, GitLab MR, Gitea PR 같은 provider 기능과 webhook delivery를 ChangeRequest 추상화와 adapter 구조로 통합한다. - [계획] Control Surface Operations UX - 경로: `agent-roadmap/phase/control-surface-operations-ux/PHASE.md` - 요약: Flutter control surface와 운영 관찰 화면을 통해 repository, operation, runner, event 흐름을 다룰 수 있게 한다. diff --git a/agent-roadmap/phase/agent-shell-iop-execution/PHASE.md b/agent-roadmap/phase/agent-shell-iop-execution/PHASE.md index 17de72f..37e1eeb 100644 --- a/agent-roadmap/phase/agent-shell-iop-execution/PHASE.md +++ b/agent-roadmap/phase/agent-shell-iop-execution/PHASE.md @@ -7,6 +7,7 @@ ## 목표 workspace 상위 sibling 프로젝트 `../agent-shell`을 제품 비종속 Flutter agent UI/package로 사용하고, 그 UI를 구동하는 backend/runtime은 `../iop` 프로젝트가 맡도록 경계를 정리한다. Gito는 agent backend를 직접 구현하지 않고, repo/workspace/operation/event control plane과 Git 결과 수렴 계약을 제공한다. +IOP 같은 sibling/external runtime 연결은 HTTP dispatch/callback 모델로 정렬하고, proto-socket은 외부 연결 규약으로 사용하지 않는다. ## Milestone 흐름 @@ -32,4 +33,5 @@ workspace 상위 sibling 프로젝트 `../agent-shell`을 제품 비종속 Flutt - agent execution backend/runtime은 `../iop` 프로젝트가 소유한다. - IOP 내부 모델 라우팅, RAG, output validation은 Gito의 소유 범위가 아니다. - control plane은 arbitrary shell command를 직접 실행하지 않고 IOP backend/runtime 결과를 Git control plane 계약으로 수렴한다. +- IOP runtime 연결은 Gito가 CLI/profile/stdin/secret injection 세부를 직접 소유하지 않는 HTTP dispatch/callback 경계로 둔다. - provider-specific PR/MR 작업은 ChangeRequest adapter Phase에서 처리한다. diff --git a/agent-roadmap/phase/agent-shell-iop-execution/milestones/iop-agent-run-bridge.md b/agent-roadmap/phase/agent-shell-iop-execution/milestones/iop-agent-run-bridge.md index 7ac9ba2..ea7fbac 100644 --- a/agent-roadmap/phase/agent-shell-iop-execution/milestones/iop-agent-run-bridge.md +++ b/agent-roadmap/phase/agent-shell-iop-execution/milestones/iop-agent-run-bridge.md @@ -7,7 +7,7 @@ ## 목표 -`../iop` backend/runtime이 수행한 agent run을 Gito의 workspace operation과 Git revision event로 수렴시키는 계약을 만든다. `../agent-shell`은 host UI/package로 남고, 실제 backend 실행과 IOP CLI/Edge/Node orchestration은 IOP 프로젝트가 소유한다. 성공 기준은 구조화 응답이 아니라 workspace의 실제 Git 상태와 push 결과로 확인한다. +`../iop` backend/runtime이 수행한 agent run을 Gito의 workspace operation과 Git revision event로 수렴시키는 계약을 만든다. `../agent-shell`은 host UI/package로 남고, 실제 backend 실행과 IOP CLI/Edge/Node orchestration은 IOP 프로젝트가 소유한다. Gito와 IOP의 외부 연결은 HTTP dispatch/callback 경계로 두며, proto-socket은 사용하지 않는다. 성공 기준은 구조화 응답이 아니라 workspace의 실제 Git 상태와 push 결과로 확인한다. ## 상태 @@ -19,14 +19,17 @@ ## 구현 잠금 -- 상태: 잠금 -- 결정 필요: - - [ ] IOP CLI 실행 명령, profile/model 선택, 입력 파일 또는 stdin 계약을 확정한다. - - [ ] IOP credential과 workspace별 secret 주입 방식을 확정한다. +- 상태: 해제 +- 결정 필요: 없음 +- 해소 근거: + - IOP CLI 실행 명령, profile/model 선택, 입력 파일 또는 stdin 계약은 Gito가 직접 확정하지 않고 IOP backend/runtime 소유로 둔다. + - IOP credential과 workspace별 secret 주입 방식은 raw secret이 아니라 `credential_ref`/`secret_ref` 경계로만 연결하며, 세부 주입은 IOP 소유 또는 후속 provider/credential Milestone에서 다룬다. + - Gito와 IOP의 외부 연결은 HTTP dispatch/callback 모델을 따른다. proto-socket은 외부 연결 규약이나 보조 transport로 사용하지 않는다. ## 범위 - IOP backend invocation/result contract +- IOP HTTP dispatch/callback boundary - workspace path, repo context, operation instruction 전달 경계 - agent run state model - IOP run success/failure 판정 @@ -64,6 +67,8 @@ agent run 결과를 Git revision과 operation event로 수렴한다. ## 범위 제외 - IOP 내부 모델 라우팅 +- IOP CLI 실행 명령, profile/model 선택, 입력 파일 또는 stdin 세부 +- IOP credential과 workspace별 raw secret 주입 세부 - `../agent-shell` package 내부 UI/domain 구현 - provider PR/MR 생성 - Plane/Jira work item lifecycle @@ -72,8 +77,9 @@ agent run 결과를 Git revision과 operation event로 수렴한다. ## 작업 컨텍스트 - 관련 경로: `services/core/internal/worker/`, `services/core/internal/gitengine/`, `services/core/internal/events/`, `packages/contracts/notes/gito-control-plane.md` -- 표준선(선택): IOP run 결과는 Git 상태와 operation event로 검증한다. +- 표준선(선택): IOP run 결과는 Git 상태와 operation event로 검증한다. Gito는 IOP CLI/secret 주입 세부를 직접 소유하지 않고 HTTP dispatch/callback과 `credential_ref`/`secret_ref` 경계만 다룬다. - 선행 작업: Agent Shell Package and IOP Backend Boundary - 후속 작업: Command Policy and Cancellation - 확인 필요: 사용자 완료 리뷰와 archive 승인 +- 방향성 정리: 외부 연결 규약에서 proto-socket을 제거하고 GitHub webhook과 유사한 HTTP webhook/callback 모델로 정렬했다. - 완료 근거: `[input]`과 `[state]`는 `packages/contracts/notes/gito-control-plane.md`의 `IOP Agent Run Bridge` 섹션에서 transport-independent `AgentRunInput`과 run state mapping으로 정리했다. `[invoke]`는 `agent-task/archive/2026/06/m-iop-agent-run-bridge/01_iop_invocation_contract/complete.log`의 PASS Roadmap Completion으로 확인했다. `[result]`는 `agent-task/archive/2026/06/m-iop-agent-run-bridge/02+01_git_result_convergence/complete.log`의 PASS Roadmap Completion으로 확인했다. `[dirty-guard]`는 `services/core/internal/worker/runner.go`의 dirty workspace failure policy와 `TestRunnerRunOnceAgentRunFailsWhenGitEvidenceIsDirty` 통과로 확인했다. `[commit-push]`는 `agent-task/archive/2026/06/m-iop-agent-run-bridge/03_commit_push_policy/complete.log`의 PASS Roadmap Completion으로 확인했다. `[revision-event]`는 `agent-task/archive/2026/06/m-iop-agent-run-bridge/04+03_revision_scan_event/complete.log`의 PASS Roadmap Completion과 `TestRuntimeScanAgentRunRevisionPublishFailureDoesNotAdvanceDurableState`, `TestScanOperationEventAllowsNullOperationID`, `cd services/core && go test ./...` 통과로 확인했다. diff --git a/agent-roadmap/phase/control-plane-foundation/PHASE.md b/agent-roadmap/phase/control-plane-foundation/PHASE.md index bbf6975..59e6ec4 100644 --- a/agent-roadmap/phase/control-plane-foundation/PHASE.md +++ b/agent-roadmap/phase/control-plane-foundation/PHASE.md @@ -6,7 +6,7 @@ ## 목표 -Gito의 초기 control plane을 build 가능한 modular monolith로 구성한다. platformless Git engine, repo/workspace/operation/event core model, Postgres 원장, proto-socket 우선 transport 경계를 정의하고 실제 구현 가능한 baseline으로 만든다. +Gito의 초기 control plane을 build 가능한 modular monolith로 구성한다. platformless Git engine, repo/workspace/operation/event core model, Postgres 원장, 외부 HTTP webhook/REST와 내부 proto-socket transport 경계를 정의하고 실제 구현 가능한 baseline으로 만든다. ## Milestone 흐름 @@ -16,7 +16,7 @@ Gito의 초기 control plane을 build 가능한 modular monolith로 구성한다 - [완료] Forgejo Branch Event MVP - 경로: `agent-roadmap/archive/phase/control-plane-foundation/milestones/forgejo-branch-event-mvp.md` - - 요약: Forgejo push webhook을 watched branch `branch.updated` event로 정규화하고 NomadCode가 proto-socket으로 받을 수 있는 MVP slice를 만든다. + - 요약: Forgejo push webhook을 watched branch `branch.updated` event로 정규화하는 MVP slice를 만든다. - [완료] Repo Registry and Workspace Lease - 경로: `agent-roadmap/archive/phase/control-plane-foundation/milestones/repo-registry-and-workspace-lease.md` @@ -32,7 +32,7 @@ Gito의 초기 control plane을 build 가능한 modular monolith로 구성한다 - [완료] Branch Event Proto-Socket Interop Readiness - 경로: `agent-roadmap/archive/phase/control-plane-foundation/milestones/branch-event-protosocket-interop-readiness.md` - - 요약: NomadCode 연동 MVP의 Gito producer slice로, `branch.updated` producer 계약을 실제 proto-socket binary wire format, consumer-neutral schema, 다중 소비자 호환 fixture 기준으로 굳힌다. + - 요약: 초기 MVP의 내부 proto-socket producer slice로, `branch.updated` event schema와 다중 소비자 호환 fixture 기준을 굳힌다. - [검토중] Runtime Scaffold and Contract Baseline - 경로: `agent-roadmap/phase/control-plane-foundation/milestones/runtime-scaffold-and-contract-baseline.md` diff --git a/agent-roadmap/phase/control-plane-foundation/milestones/runtime-scaffold-and-contract-baseline.md b/agent-roadmap/phase/control-plane-foundation/milestones/runtime-scaffold-and-contract-baseline.md index 16d33bd..5086c00 100644 --- a/agent-roadmap/phase/control-plane-foundation/milestones/runtime-scaffold-and-contract-baseline.md +++ b/agent-roadmap/phase/control-plane-foundation/milestones/runtime-scaffold-and-contract-baseline.md @@ -27,7 +27,7 @@ Gito를 독립 프로젝트로 시작할 수 있도록 Go core, Flutter control - Go `server`, `worker`, `shell` command scaffold - `controlplane`, `core`, `gitengine`, `worker`, `agentshell`, `provider`, `events`, `storage` package boundary - Flutter control surface placeholder -- proto-socket 우선, REST 예외, gRPC 제외 transport 정책 +- 외부 HTTP webhook/REST, 내부 proto-socket, gRPC 제외 transport 정책 - README와 architecture 문서 - agent-ops rules, skills, local test 진입점 @@ -39,7 +39,7 @@ Gito의 초기 작업자가 경계와 명령을 바로 이해할 수 있는 repo - [x] [go-cmds] Go `server`, `worker`, `shell` command를 build 가능한 상태로 둔다. 검증: `bin/build`가 `gito-server`, `gito-worker`, `gito-shell`을 생성한다. - [x] [domain-packages] core domain, gitengine, provider, events, storage, worker, agentshell package boundary를 만든다. 검증: `cd services/core && go test ./...` PASS. -- [x] [contracts] proto-socket 우선 transport, REST 예외, gRPC 제외, event/DTO 후보를 contracts note에 기록한다. +- [x] [contracts] 외부 HTTP webhook/REST, 내부 proto-socket, gRPC 제외, event/DTO 후보를 contracts note에 기록한다. - [x] [readme] README를 사람과 AI가 함께 읽는 작업 진입점으로 보강한다. - [x] [protosocket-surface] proto-socket placeholder를 channel/action registry scaffold로 전환한다. 검증: proto-socket route test가 operation/event channel placeholder를 확인한다. - [x] [storage-boundary] Postgres migration과 storage boundary를 실제 store interface 기준으로 연결한다. 검증: storage package test가 repo/operation/event 기본 CRUD 또는 interface contract를 확인한다. diff --git a/agent-roadmap/phase/provider-change-request-integration/PHASE.md b/agent-roadmap/phase/provider-change-request-integration/PHASE.md index 8fcb809..41420d2 100644 --- a/agent-roadmap/phase/provider-change-request-integration/PHASE.md +++ b/agent-roadmap/phase/provider-change-request-integration/PHASE.md @@ -6,7 +6,7 @@ ## 목표 -GitHub PR, GitLab MR, Gitea PR 같은 provider 기능을 provider-neutral ChangeRequest 인터페이스로 묶는다. Webhook은 빠른 wakeup signal로 사용하되, 최종 상태 판정은 Git revision/diff와 provider read API로 재검증한다. +GitHub PR, GitLab MR, Gitea PR 같은 provider 기능을 provider-neutral ChangeRequest 인터페이스로 묶는다. 외부 연동은 GitHub webhook과 유사한 HTTP webhook/callback 모델로 맞추고, Webhook은 빠른 wakeup signal로 사용하되 최종 상태 판정은 Git revision/diff와 provider read API로 재검증한다. ## Milestone 흐름 @@ -24,7 +24,7 @@ GitHub PR, GitLab MR, Gitea PR 같은 provider 기능을 provider-neutral Change - [계획] Webhook Revision Reconcile - 경로: `agent-roadmap/phase/provider-change-request-integration/milestones/webhook-revision-reconcile.md` - - 요약: provider webhook, polling, Git revision scan을 같은 변경 event로 정규화하고 재검증한다. + - 요약: provider webhook, outbound consumer webhook, polling, Git revision scan을 같은 변경 event로 정규화하고 재검증한다. ## Phase 경계 @@ -32,4 +32,4 @@ GitHub PR, GitLab MR, Gitea PR 같은 provider 기능을 provider-neutral Change - provider adapter는 PR/MR/review/checks/comment/webhook 같은 플랫폼 API만 맡는다. - provider별 credential 원문은 tracked 파일에 저장하지 않고 credential ref로만 연결한다. - provider webhook만으로 상태를 확정하지 않고 Git revision 또는 provider read API로 확인한다. - +- 외부 consumer event delivery는 HTTP webhook/callback으로 제공하며 proto-socket을 외부 연결 규약이나 보조 transport로 제공하지 않는다. diff --git a/agent-roadmap/phase/provider-change-request-integration/milestones/webhook-revision-reconcile.md b/agent-roadmap/phase/provider-change-request-integration/milestones/webhook-revision-reconcile.md index 6d034d5..a783347 100644 --- a/agent-roadmap/phase/provider-change-request-integration/milestones/webhook-revision-reconcile.md +++ b/agent-roadmap/phase/provider-change-request-integration/milestones/webhook-revision-reconcile.md @@ -7,7 +7,7 @@ ## 목표 -provider webhook, provider polling, Git revision scan을 같은 변경 입력으로 정규화한다. Webhook은 빠른 wakeup signal이지만 최종 판정은 Git revision/diff 또는 provider read API로 재검증해 중복 적용과 누락을 줄인다. +provider webhook, outbound consumer webhook, provider polling, Git revision scan을 같은 변경 입력으로 정규화한다. Webhook은 빠른 wakeup signal이지만 최종 판정은 Git revision/diff 또는 provider read API로 재검증해 중복 적용과 누락을 줄인다. 외부 event delivery는 GitHub webhook과 유사한 HTTP callback 방식으로 제공하고, proto-socket은 외부 연결 규약에서 제외한다. ## 상태 @@ -26,6 +26,8 @@ provider webhook, provider polling, Git revision scan을 같은 변경 입력으 - webhook received event - branch updated event +- consumer webhook subscription과 HTTP delivery +- delivery idempotency, signature, retry/backoff - provider polling fallback - revision mismatch conflict - idempotency key와 expected revision @@ -41,6 +43,14 @@ provider webhook, provider polling, Git revision scan을 같은 변경 입력으 - [ ] [poll-source] provider polling fallback shape를 정의한다. - [ ] [git-source] Git revision scan event와 provider event를 같은 identity로 연결한다. +### Epic: [delivery] Webhook delivery + +정규화된 event를 외부 consumer가 제공한 HTTP endpoint로 전달한다. + +- [ ] [subscription] consumer endpoint, event type, repo/branch filter, `secret_ref`를 등록하는 형식을 정의한다. +- [ ] [deliver] `branch.updated` 같은 normalized event를 signed HTTP POST로 전달한다. 검증: fake consumer endpoint가 delivery id와 payload를 수신한다. +- [ ] [retry] delivery idempotency, retry/backoff, failed delivery 상태를 PostgreSQL 기준으로 기록한다. + ### Epic: [reconcile] Reconcile policy 변경 적용 전 재검증과 conflict 처리를 수행한다. @@ -64,13 +74,13 @@ provider webhook, provider polling, Git revision scan을 같은 변경 입력으 - provider별 모든 webhook payload 지원 - real-time delivery 보장 - Redis Streams fanout +- proto-socket external consumer delivery - UI conflict resolution 화면 ## 작업 컨텍스트 - 관련 경로: `services/core/internal/events/`, `services/core/internal/provider/`, `services/core/internal/gitengine/`, `services/core/internal/worker/` -- 표준선(선택): webhook은 빠른 신호이고 확정은 Git revision/diff 또는 provider read API로 수행한다. +- 표준선(선택): webhook은 빠른 신호이고 확정은 Git revision/diff 또는 provider read API로 수행한다. 외부 event delivery는 HTTP webhook/callback이며 proto-socket은 내부 control/runtime 규약으로만 남긴다. - 선행 작업: Change Request Abstraction - 후속 작업: Flutter Control Surface Baseline - 확인 필요: 없음 - diff --git a/docs/architecture.md b/docs/architecture.md index c1d32e3..06320ba 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -10,10 +10,10 @@ sibling `../iop` project. ### Control Plane -- Owns proto-socket and REST surfaces. +- Owns external REST API/webhook surfaces and internal proto-socket surfaces. - Accepts user, automation, and provider callback requests. - Applies auth, policy, and approval gates. -- Creates operations and exposes event streams. +- Creates operations and delivers normalized events. - Does not execute Git commands directly. ### Core Domain @@ -59,14 +59,16 @@ sibling `../iop` project. - Treat webhooks as wakeup signals. Final state must be verified through Git revision or provider read APIs. - MVP priority is Forgejo push intake: provider webhooks enter through REST - callbacks, then Gito emits normalized branch events for internal proto-socket - consumers such as NomadCode. + callbacks, then Gito records normalized branch events. External consumers + receive them through signed HTTP webhook delivery, not proto-socket. ## Transport -- proto-socket is the default internal runtime transport. -- REST is reserved for health/readiness, provider callbacks, smoke/curl, and - simple bootstrap endpoints. +- REST is the external integration surface for provider callbacks, public APIs, + HTTP webhook delivery, health/readiness, smoke/curl, and simple bootstrap + endpoints. +- proto-socket is internal-only control/runtime transport. It is not an external + integration contract and is not offered as a fallback consumer transport. - gRPC is intentionally out of scope for the initial architecture. ## Event Policy diff --git a/packages/contracts/README.md b/packages/contracts/README.md index 2cdb157..d5c7919 100644 --- a/packages/contracts/README.md +++ b/packages/contracts/README.md @@ -2,7 +2,6 @@ This package records transport-independent contract candidates for Gito. -Use it for proto-socket channel/action notes, REST compatibility maps, event -schemas, provider-neutral DTOs, and compatibility notes shared by the Go core and -Flutter client. - +Use it for HTTP webhook/REST compatibility maps, event schemas, +provider-neutral DTOs, internal proto-socket channel/action notes, and +compatibility notes shared by the Go core and Flutter client. diff --git a/packages/contracts/notes/gito-control-plane.md b/packages/contracts/notes/gito-control-plane.md index 1e402d1..ea7b8d6 100644 --- a/packages/contracts/notes/gito-control-plane.md +++ b/packages/contracts/notes/gito-control-plane.md @@ -2,12 +2,20 @@ ## Transport Policy -- Internal runtime calls use proto-socket first. -- REST remains for health/readiness, provider callbacks, smoke/curl, and simple - bootstrap endpoints. +- External provider and consumer integrations use REST APIs and HTTP + webhook/callback delivery. Gito should feel compatible with GitHub/GitLab/Gitea + webhook integration patterns rather than requiring a Gito-specific binary + client. +- proto-socket is internal-only control/runtime transport. It is not an external + provider, consumer, IOP, or fallback integration contract. +- REST remains for health/readiness, provider callbacks, external webhook + delivery, smoke/curl, and simple bootstrap endpoints. - gRPC is excluded from the first design. -## proto-socket Channels +## Internal proto-socket Channels + +These channels describe Gito-internal control/runtime surfaces. They must not be +used as the canonical contract for external consumers or sibling projects. | Channel | Purpose | | --- | --- | @@ -17,13 +25,13 @@ | `git` | Request platformless Git operations. | | `change_request` | Manage provider-neutral PR/MR operations. | | `agent_shell` | Reserved/legacy shell scaffold metadata; canonical agent UI is `../agent-shell` and backend/runtime is `../iop`. | -| `event` | Subscribe to normalized events. | +| `event` | Internal subscription/projection of normalized events. | -## proto-socket Action Registry Scaffold +## Internal proto-socket Action Registry Scaffold -The first proto-socket surface exposes channel/action registry metadata before -real command execution. Every listed action starts as `placeholder` until its -own Milestone wires storage, worker, or provider behavior. +The first internal proto-socket surface exposes channel/action registry metadata +before real command execution. Every listed action starts as `placeholder` until +its own Milestone wires storage, worker, or provider behavior. | Channel | Placeholder actions | | --- | --- | @@ -37,10 +45,11 @@ own Milestone wires storage, worker, or provider behavior. ## REST Bootstrap Exceptions -REST may expose temporary repo bootstrap helpers for smoke/curl setup while the -proto-socket `repo` channel is still placeholder-only. Those helpers must stay -limited to bootstrap registration, lookup, and listing, and must use the same -Repo DTO fields documented below. +REST is the canonical external surface for provider callbacks, public APIs, and +webhook delivery. Temporary repo bootstrap helpers for smoke/curl setup may +exist while richer operation APIs are still placeholder-only. Those helpers must +stay limited to bootstrap registration, lookup, and listing, and must use the +same Repo DTO fields documented below. ## Agent Shell / IOP Boundary @@ -55,9 +64,10 @@ provider-neutral Git results. IOP owns agent execution, shell command execution, model/runtime routing, command policy, cancellation, and log redaction source of truth. Gito may persist IOP results only after they are expressed as operation state, Git revision/diff, workspace lease state, or normalized event records. -The IOP bridge below is the transport-independent contract candidate for this -Milestone. It does not choose the concrete IOP CLI command, profile/model, -stdin/input-file shape, or secret injection mechanism. +The IOP bridge below keeps the payload fields transport-neutral, while the +external IOP connection shape is HTTP dispatch/callback. It does not choose the +concrete IOP CLI command, profile/model, stdin/input-file shape, or secret +injection mechanism. proto-socket is not part of the IOP contract. ## IOP Agent Run Bridge @@ -66,6 +76,9 @@ IOP through an adapter boundary. Gito must not execute the IOP CLI or arbitrary workspace commands directly. IOP may run through CLI, Edge, Node, or another runtime, but Gito only records the result once it is expressed as operation state, Git workspace evidence, or normalized event records. +The preferred external shape is GitHub-like webhook/callback: Gito sends an +agent run intent to an IOP HTTP endpoint or registered runtime adapter, and IOP +posts sanitized state/result updates back to a Gito callback endpoint. ### AgentRunInput @@ -79,6 +92,7 @@ state, Git workspace evidence, or normalized event records. | `policy_context` | JSON object with Gito-known policy context, approvals, and allowed result actions; IOP remains source of truth for command policy decisions. See policy keys below. | | `expected_revision` | Optional workspace HEAD before IOP starts, used later for revision diff checks. | | `credential_refs` | Optional list or map of credential references. Values point to secrets outside tracked contracts and logs. | +| `result_callback` | Optional HTTP callback descriptor for IOP state/result delivery. Raw callback secrets are forbidden; use `credential_ref` or `secret_ref` references only. | #### policy_context Keys @@ -120,9 +134,10 @@ Forgejo branch event delivery is now a provided contract: `agent-contract/provided/gito-forgejo-branch-events-v1.md`. Read that contract when working on Forgejo webhook intake, `branch.updated` -events, `event.subscribe`, NomadCode branch event wakeups, or the -`/callbacks/forgejo/push` and `/api/listeners/branches` surfaces. This note keeps -only the proto-socket channel registry and DTO candidate overview. +events, outbound HTTP webhook delivery, NomadCode branch event wakeups, or the +`/callbacks/forgejo/push`, `/api/listeners/branches`, and webhook subscription +surfaces. This note keeps only the internal proto-socket channel registry and DTO +candidate overview. ## Core DTO Candidates @@ -230,16 +245,29 @@ with `subject=operation:`. - Stored payloads are JSON objects and map to `events.Event.Payload` with `events.PayloadEncodingJSON`. - Outbox readers list events in `(created_at, id)` order. -- Publish retry state belongs to the outbox store boundary; Redis, if added - later, only accelerates fanout. +- Publish retry state belongs to the outbox/webhook delivery boundary; Redis, if + added later, only accelerates fanout. -### proto-socket Event Mapping +### External Webhook Delivery -- Stored `type` maps to proto-socket `action` on the `event` channel. +- Registered consumers provide an HTTP endpoint, accepted event types, optional + repo/branch filters, and a `secret_ref` for delivery signing. +- Gito delivers normalized events as JSON over HTTP POST. The body uses the + durable event envelope and payload fields, without provider secrets or raw + credential values. +- Delivery headers include event type, delivery id, and an HMAC signature when a + signing secret is configured. +- Consumers treat webhook deliveries as wakeup signals and verify final state + through Git revision scans or provider read APIs before mutating their own + source-of-truth state. +- Delivery idempotency, retry/backoff, and failed delivery state belong to the + webhook delivery worker, backed by PostgreSQL. + +### Internal proto-socket Event Projection + +- Stored `type` may map to proto-socket `action` on the internal `event` + channel for Gito-owned control/runtime consumers. - Stored `payload` maps to the proto-socket envelope `payload` object without provider secrets or credential values. -- `event.subscribe` filters by event name and optional payload fields such as - `repo_id` and `branch`. -- `event.list` returns recent event payloads for smoke/debug use. -- `event.ack` remains placeholder-only until a durable cursor or delivery - acknowledgement Milestone explicitly scopes it. +- This projection is internal-only and must not be documented as an external + consumer integration path.