273 lines
13 KiB
Markdown
273 lines
13 KiB
Markdown
# Gito Control Plane Contract Candidates
|
|
|
|
## Transport Policy
|
|
|
|
- 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.
|
|
|
|
## 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 |
|
|
| --- | --- |
|
|
| `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` | Internal subscription/projection of normalized events. |
|
|
|
|
## Internal proto-socket Action Registry Scaffold
|
|
|
|
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 |
|
|
| --- | --- |
|
|
| `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 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
|
|
|
|
`../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.
|
|
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
|
|
|
|
Gito creates and owns an `agent_run` Operation, then hands execution intent to
|
|
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
|
|
|
|
| Field | Meaning |
|
|
| --- | --- |
|
|
| `operation_id` | Existing Gito operation id with `type=agent_run`. |
|
|
| `repo` | Repo snapshot containing `id`, `remote_url`, `default_branch`, and optional `credential_ref`; raw credential values are forbidden. |
|
|
| `branch` | Branch checked out in the leased workspace. |
|
|
| `workspace_path` | Absolute path of the leased workspace slot that IOP may use. |
|
|
| `instruction` | User or automation instruction text for the run. |
|
|
| `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
|
|
|
|
Transport-independent keys Gito reads from `policy_context`. IOP may add its own keys; Gito ignores unknown ones.
|
|
|
|
| Key | Type | Meaning |
|
|
| --- | --- | --- |
|
|
| `commit_push` | boolean | `true` to allow Gito to commit and push after a successful agent run. |
|
|
| `allowed_result_actions` | string array | Alternative form; presence of `"commit_push"` in the list enables commit and push. |
|
|
| `commit_message` | string | Commit message to use when commit/push is allowed. Defaults to `"agent run result: <operation_id>"`. |
|
|
| `remote` | string | Git remote name for push. Defaults to `"origin"`. |
|
|
| `branch` | string | Branch to push. Defaults to `AgentRunInput.branch`. |
|
|
|
|
Raw credential values must not appear in `policy_context`. When commit/push is allowed, Gito uses the credential environment already present in the workspace; it does not inject secrets from `policy_context`.
|
|
|
|
### AgentRunState Mapping
|
|
|
|
| IOP run state | Gito operation lifecycle |
|
|
| --- | --- |
|
|
| `queued` | Operation exists as `queued`; IOP execution has not been accepted yet. |
|
|
| `running` | Operation moves to `running`; Gito may append `operation.started` and `agent.run.started` records. |
|
|
| `succeeded` | IOP reports successful execution. Gito marks `succeeded` only after the Git result confirmation step accepts workspace status and revision evidence. |
|
|
| `failed` | Operation moves to `failed`; Gito records sanitized failure context without raw logs or secrets. |
|
|
| `cancelled` | Operation moves to terminal `cancelled`; cancellation policy/event details belong to the command policy and cancellation Milestone. |
|
|
|
|
Structured IOP output is advisory. The success source of truth for this bridge is
|
|
the Git workspace after the run: status, before/after revision, changed files,
|
|
and any later commit/push result allowed by policy. When a policy-allowed push is completed, Gito triggers a revision scan to detect the newly updated revision and emit the corresponding branch update event. The results are recorded in the operation completion payload:
|
|
|
|
- `revision_scan_attempted` (boolean): `true` if a revision scan was triggered after a successful push.
|
|
- `revision_event_matched` (boolean): `true` if the scanner matched the new revision and successfully generated/published the event.
|
|
- `revision_event_id` (string, optional): The ID of the generated revision event if matched.
|
|
|
|
If the scan fails, the operation moves to `failed` and a sanitized scan error message is recorded.
|
|
|
|
## 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, 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
|
|
|
|
### 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:<operation_id>` or `repo:<repo_id>`. |
|
|
| `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:<operation_id>`.
|
|
|
|
| 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/webhook delivery boundary; Redis, if
|
|
added later, only accelerates fanout.
|
|
|
|
### External Webhook Delivery
|
|
|
|
- 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.
|
|
- This projection is internal-only and must not be documented as an external
|
|
consumer integration path.
|