# Gito Control Plane Contract Candidates ## Transport Policy - Internal runtime calls use proto-socket first. - REST remains for health/readiness, provider callbacks, smoke/curl, and simple bootstrap endpoints. - gRPC is excluded from the first design. ## proto-socket Channels | Channel | Purpose | | --- | --- | | `repo` | Register, inspect, and list managed repositories. | | `workspace` | Lease, release, and inspect workspace slots. | | `operation` | Create, cancel, inspect, and stream operations. | | `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. | ## 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. | Channel | Placeholder actions | | --- | --- | | `repo` | `register`, `get`, `list` | | `workspace` | `lease`, `release`, `get` | | `operation` | `create`, `cancel`, `get`, `stream` | | `git` | `clone`, `fetch`, `status`, `diff`, `commit`, `push` | | `change_request` | `open`, `update`, `list` | | `agent_shell` | `heartbeat`, `dispatch`, `stream_logs` remain placeholder-only until an explicit compatibility Milestone scopes them. | | `event` | `subscribe`, `list`, `ack` | ## 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. ## Agent Shell / IOP Boundary `../agent-shell` is the product-agnostic Flutter package for agent interaction UI and domain models. It is not the Gito backend. Hosts that use that package should depend on it as `agent_shell: path: ../agent-shell` and route agent runtime/backend behavior through the sibling `../iop` project. Gito's responsibility is the Git control plane boundary: repository registry, workspace leases, operations, revision events, durable event records, and 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. Gito must not expose a competing agent execution API from this contract note unless a later Milestone explicitly defines an IOP bridge contract. ## MVP: Forgejo Branch Event Flow 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. ## Core DTO Candidates ### Repo | Field | Meaning | | --- | --- | | `id` | Stable Gito repo id. | | `name` | Display name. | | `remote_url` | Git remote URL. | | `default_branch` | Default source-of-truth branch. | | `workspace_root` | Local workspace root for slots. | | `credential_ref` | Reference to credentials, never the raw secret. | ### WorkspaceLease | Field | Meaning | | --- | --- | | `id` | Lease id. | | `repo_id` | Managed repo id. | | `slot` | Zero-padded slot index. | | `path` | Local workspace path. | | `state` | `available`, `leased`, `dirty`, or `error`. | | `expires_at` | Optional lease expiry. | ### Operation | Field | Meaning | | --- | --- | | `id` | Operation id. | | `repo_id` | Target repo. | | `type` | `clone`, `fetch`, `commit`, `push`, `agent_run`, etc. | | `state` | `queued`, `running`, `succeeded`, `failed`, `cancelled`. | | `idempotency_key` | Duplicate guard. | | `created_by` | Actor id or system source. | ### RevisionEvent | Field | Meaning | | --- | --- | | `repo_id` | Target repo. | | `branch` | Branch name. | | `before` | Previous revision. | | `after` | New revision. | | `changed_files` | Changed file paths and change types. | | `observed_at` | Observation timestamp. | ### ChangeRequest Provider-neutral abstraction for GitHub PR, GitLab MR, Gitea PR, and similar platform features. | Field | Meaning | | --- | --- | | `provider` | `github`, `gitlab`, `gitea`, etc. | | `external_id` | Provider PR/MR id. | | `repo_id` | Target repo. | | `source_branch` | Source branch. | | `target_branch` | Target branch. | | `state` | `open`, `merged`, `closed`, `draft`, etc. | ## Normalized Events Durable event records use a stable envelope: | Field | Meaning | | --- | --- | | `id` | Stable event id generated by Gito. | | `type` | Normalized event name from the table below. | | `subject` | Entity anchor such as `operation:` or `repo:`. | | `payload` | JSON object encoded as `application/json`; raw provider secrets and credential values are forbidden. | | `created_at` | Time Gito recorded the event. | | Event | Meaning | | --- | --- | | `repo.changed` | Repo registry changed. | | `branch.updated` | Watched branch revision changed, initially from Forgejo push webhooks or future revision scans. | | `workspace.leased` | Workspace lease acquired. | | `workspace.released` | Workspace lease released. | | `workspace.dirty` | Workspace has uncommitted changes. | | `operation.started` | Operation execution started. | | `operation.completed` | Operation succeeded. | | `operation.failed` | Operation failed. | | `agent.run.started` | Agent execution started. | | `agent.run.completed` | Agent execution completed. | | `change_request.opened` | PR/MR-like object opened. | | `change_request.updated` | PR/MR-like object changed. | | `change_request.merged` | PR/MR-like object merged. | | `provider.webhook.received` | Provider webhook received. | ### Operation Event Payloads Operation lifecycle events are stored in the outbox as normalized event records with `subject=operation:`. | Event | Required payload fields | | --- | --- | | `operation.started` | `operation_id`, `repo_id`, `type`, `state`, `started_at` | | `operation.completed` | `operation_id`, `repo_id`, `type`, `state`, `completed_at` | | `operation.failed` | `operation_id`, `repo_id`, `type`, `state`, `failed_at`, optional `error` | ### Outbox Storage Contract - PostgreSQL is the source of truth for durable events. - 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. ### proto-socket Event Mapping - Stored `type` maps to proto-socket `action` on the `event` channel. - 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.