update: modify files for gito project

This commit is contained in:
toki 2026-06-15 22:13:27 +09:00
parent 593266ccfc
commit 3ea2279d51
4 changed files with 30 additions and 9 deletions

View file

@ -18,6 +18,9 @@ Flutter client는 control surface 경계만 잡혀 있다.
- Go `server`, `worker` command build
- health/readiness REST placeholder
- 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` 최소 테스트
- core domain DTO 후보
- provider-neutral `ChangeRequest` adapter 경계
@ -26,13 +29,12 @@ Flutter client는 control surface 경계만 잡혀 있다.
아직 구현 전인 범위:
- 실제 proto-socket channel/action
- 실제 PostgreSQL store wiring
- `event` 외 proto-socket channel/action의 실제 command behavior
- `agent_shell: path: ../agent-shell` package를 쓰는 Flutter host
integration
- `../iop` backend/runtime 결과를 Gito operation/event 계약으로 수렴시키는
연결
- GitHub/GitLab/Gitea provider adapter
- GitHub/GitLab/Gitea provider adapter와 Forgejo PR/MR adapter
- Flutter 화면 구성과 operation event 구독
## 빠른 시작
@ -161,9 +163,10 @@ Provider Adapters
| --- | --- | --- |
| `APP_ENV` | runtime 환경 이름, 기본값 `local` | 아니오 |
| `HTTP_ADDR` | server listen address, 기본값 `:8080` | 아니오 |
| `DATABASE_URL` | PostgreSQL connection string | 실제 storage wiring 이후 필요 |
| `DATABASE_URL` | PostgreSQL connection string, 없으면 in-memory runtime 사용 | 아니오 |
| `REDIS_URL` | optional Redis endpoint | 아니오 |
| `PROTO_SOCKET_PATH` | proto-socket endpoint path, 기본값 `/proto-socket` | 아니오 |
| `FORGEJO_WEBHOOK_SECRET` | Forgejo push callback HMAC-SHA256 서명 키, 없으면 검증 생략 | 아니오 |
| `WORKER_ENABLED` | worker 실행 여부, 기본값 `true` | 아니오 |
Credential 값은 tracked 파일에 쓰지 않는다. 필요한 경우 `credential_ref`나 ignored local secret file로 연결한다.

View file

@ -342,7 +342,7 @@ listener bootstrap, `/proto-socket`, `/api/listeners/branches`, `/api/events`를
| 변수 | 필수 | 기본값 | 설명 |
| --- | --- | --- | --- |
| `APP_ENV` | 아니오 | `development` | 앱 환경 |
| `GITO_PROTO_SOCKET_PATH` | 아니오 | `/proto-socket` | proto-socket WebSocket 경로 |
| `PROTO_SOCKET_PATH` | 아니오 | `/proto-socket` | proto-socket WebSocket 경로 |
| `FORGEJO_WEBHOOK_SECRET` | 아니오 | (없으면 서명 검증 생략) | Forgejo webhook 서명 키 |
| `DATABASE_URL` | 아니오 | (없으면 in-memory) | PostgreSQL DSN |

View file

@ -168,10 +168,6 @@ func handleForgejoPush(cfg config.Config, runtime *Runtime) http.HandlerFunc {
writeJSON(w, http.StatusMethodNotAllowed, map[string]string{"error": "method not allowed"})
return
}
if eventName := webhookEventName(r); eventName != "" && eventName != "push" {
writeJSON(w, http.StatusAccepted, map[string]any{"accepted": true, "matched": false, "reason": "unsupported event"})
return
}
body, err := io.ReadAll(io.LimitReader(r.Body, 1<<20))
if err != nil {
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "failed to read payload"})
@ -182,6 +178,10 @@ func handleForgejoPush(cfg config.Config, runtime *Runtime) http.HandlerFunc {
writeJSON(w, http.StatusUnauthorized, map[string]string{"error": "invalid forgejo signature"})
return
}
if eventName := webhookEventName(r); eventName != "" && eventName != "push" {
writeJSON(w, http.StatusAccepted, map[string]any{"accepted": true, "matched": false, "reason": "unsupported event"})
return
}
payload, err := forgejo.ParsePushPayload(body)
if err != nil {
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid forgejo push payload"})

View file

@ -180,6 +180,24 @@ func TestForgejoPushIgnoresUnwatchedBranch(t *testing.T) {
}
}
func TestForgejoPushRequiresSignatureBeforeIgnoringUnsupportedEvent(t *testing.T) {
router := NewRouter(config.Config{
AppEnv: "test",
ProtoSocketPath: "/proto-socket",
ForgejoWebhookSecret: "forgejo-secret",
}, slog.Default())
req := httptest.NewRequest(http.MethodPost, "/callbacks/forgejo/push", bytes.NewBufferString(`{"unsupported":true}`))
req.Header.Set("X-Forgejo-Event", "repository")
rec := httptest.NewRecorder()
router.ServeHTTP(rec, req)
if rec.Code != http.StatusUnauthorized {
t.Fatalf("status: got %d body=%s", rec.Code, rec.Body.String())
}
}
func TestEventSubscribeRegistersConnectionFilter(t *testing.T) {
dispatcher := protosocket.NewDispatcher()
runtime := NewRuntime(nil)