Generated Korvus v1 Protobuf and Connect API
- gen/korvus/v1/incident.pb.go
- gen/korvus/v1/session.pb.go
- gen/korvus/v1/system.pb.go
- gen/korvus/v1/korvusv1connect/incident.connect.go
- gen/korvus/v1/korvusv1connect/session.connect.go
- gen/korvus/v1/korvusv1connect/system.connect.go
- IncidentServiceClient
- IncidentServiceHandler
- SessionServiceClient
- SessionServiceHandler
- SystemServiceClient
- SystemServiceHandler
Relevant source files · 12
- buf.yaml 1–8
- buf.gen.yaml 4–12, 24–36
- .gitlab-ci.yml 116–122, 407–418
- gen/korvus/v1/system.pb.go 1–5, 1040, 1107–1128
- gen/korvus/v1/incident.pb.go 1, 1549–1571
- gen/korvus/v1/session.pb.go 1, 3196–3228
- gen/korvus/v1/korvusv1connect/incident.connect.go 1, 19, 22–24, 33–58 +5 more
- gen/korvus/v1/korvusv1connect/session.connect.go 1, 72–114, 267–309
- gen/korvus/v1/korvusv1connect/system.connect.go 1, 57–78, 171–192
- internal/transport/transport.go 127–180
- internal/transport/incident.go 27–31, 42–70, 94–106
- .golangci.yml 77–79
The gen/ tree is Korvus's wire contract. Everything a client can ask a running Korvus to do — open an incident, start a session, watch it live, read the report, list the configured MCP servers — is declared once in the korvus.v1 Protobuf package and then compiled into two artifacts: the Go message and service bindings under gen/korvus/v1/, and the TypeScript bindings under gen/ts/ (covered in Generated TypeScript Client Types). This page covers the Go half: the three .pb.go files that define the messages, and the three .connect.go files that define the Connect clients and handlers.
The reason this tree exists as a separate, checked-in directory rather than something generated on the fly is reproducibility. The Buf configuration pins a module rooted at api and lints it against the STANDARD ruleset buf.yaml, while buf.gen.yaml pins three remote plugins — protocolbuffers/go, connectrpc/go and bufbuild/es — so no local protoc-gen-* binaries are needed to reproduce the output buf.gen.yaml. Because the Go output is checked in, the CI pipeline can regenerate it and fail the build if the committed tree has drifted from the protos; the buf:verify job runs buf generate and then rejects any non-empty git diff CI configuration. The paths-proto change filter wires api/**/*, gen/**/* and buf.yaml into that job's rules CI configuration.
The .pb.go files are ordinary protoc-gen-go output. Each opens with the generator banner and the pinned protoc-gen-go v1.36.10 version system.pb.go, and each ends with an init() that builds the file descriptor via protoimpl.TypeBuilder. The incident file declares 4 enums, 22 messages and 1 service incident.pb.go; the session file declares 5 enums, 35 messages and 1 service session.pb.go; the system file declares 18 messages and 1 service system.pb.go. The Go package name is korvusv1, derived from the go_package option that the raw descriptor carries as gitlab.com/ajxpublic/korvus/gen/korvus/v1;korvusv1 system.pb.go.
The .connect.go files sit in a sibling package, korvusv1connect, and are protoc-gen-connect-go output. Each file is guarded by a compile-time assertion that the generated code matches the connect library version compiled into the binary — connect.IsAtLeastVersion1_13_0 incident.connect.go — so a version skew is a compile error rather than a runtime surprise.
How it works
Each .connect.go file follows the same four-part shape. First, a set of constants: the fully-qualified service name ("korvus.v1.IncidentService" incident.connect.go) and one procedure constant per RPC, formatted as /korvus.v1.IncidentService/CreateIncident incident.connect.go. Those strings are simultaneously the Connect Spec.Procedure, the gRPC method path and the final two segments of the HTTP route, so a single constant serves all three protocols.
Second, a client interface. IncidentServiceClient incident.connect.go has one method per RPC, each taking a *connect.Request[T] and returning a *connect.Response[T]. The streaming RPCs break the pattern in a useful way: WatchIncidents returns a *connect.ServerStreamForClient[v1.WatchIncidentsResponse] rather than a single response incident.connect.go, so a caller gets an iterator-shaped handle instead of one buffered payload. SessionServiceClient follows the same shape across eleven RPCs session.connect.go and SystemServiceClient across six system.connect.go.
The client constructor, NewIncidentServiceClient, trims the trailing slash off the base URL and then builds one connect.Client per method, pointing each at baseURL + <procedure constant> and attaching the method's schema from the compiled descriptor incident.connect.go. The schema lookup goes through v1.File_korvus_v1_incident_proto.Services().ByName("IncidentService").Methods() — the descriptor exported by the .pb.go file — so the client and the message definitions cannot drift apart. By default the client speaks the Connect protocol with the binary Protobuf codec and asks for gzipped responses; connect.WithGRPC() and connect.WithGRPCWeb() switch protocols without changing anything else.
Third, the handler interface — the server-side mirror of the client. IncidentServiceHandler incident.connect.go, SessionServiceHandler session.connect.go and SystemServiceHandler system.connect.go each declare the same method names, with server-streaming methods taking a *connect.ServerStream[T] instead of returning one.
Fourth, the handler constructor. NewIncidentServiceHandler returns the mount path and the http.Handler to serve on it incident.connect.go. Internally it builds one connect.NewUnaryHandler per unary RPC and one connect.NewServerStreamHandler for WatchIncidents, each tagged with its descriptor schema, then returns a single http.HandlerFunc that switches on r.URL.Path and dispatches to the matching handler — anything else gets http.NotFound. The mount path is the service name with a trailing slash, /korvus.v1.IncidentService/, which is why the three services can share one mux without colliding.
Finally, each file provides an Unimplemented…ServiceHandler struct whose every method returns connect.CodeUnimplemented with a message naming the RPC incident.connect.go. This is the forward-compatibility hatch: adding an RPC to the proto makes the interface grow, and a server that embeds the struct keeps compiling.
How the server wires this up
The generated handlers are mounted by the transport package, which builds one mux holding all three services, /healthz, and the Alertmanager webhook transport.NewMux. The mount path returned by NewIncidentServiceHandler is registered with mux.Handle, so the routing that Connect performs internally and the routing net/http performs at the service level are separate concerns.
The transport does not implement the handler interfaces directly. It declares a variable of the generated handler type and swaps in the real implementation only when the corresponding subsystem is present: var incidentImpl korvusv1connect.IncidentServiceHandler = unimplementedIncidentService{}, replaced by &incidentService{manager: opts.Incidents} when an incident manager is wired in transport.NewMux, and the same pattern for the session service, whose handler needs the session store, broadcaster, lifecycle, defaults, workspace and download signer transport.NewMux. The system service is always mounted, since it only reports on process state transport.NewMux. This is the seam described in Connect API Server and Service Handlers.
The fallback implementations are the transport's own, not the generated ones. internal/transport/incident.go defines unimplementedIncidentService, which answers every RPC with connect.CodeUnimplemented but distinguishes two causes incident.go: the five lifecycle RPCs return errNoIncidentManager ("this process was started without an incident manager"), while ListAlerts and WatchIncidents return errAlertPathNotImplemented incident.go. The distinction is deliberate — the source comment explains that a single sentinel would have told a client hitting ListAlerts on a fully wired server that the process was a transport-only stub. The concrete incidentService embeds this fallback so the two alert-path RPCs stay unimplemented while the five lifecycle RPCs are overridden incident.go. The semantics behind those RPCs live in Incident Manager: Open, List, Update, Close, Alert Ingestion, Fingerprinting and Debounce and Session Manager and Lifecycle; the conversion between store types and Protobuf messages is in Watch Streams, Read APIs, Webhooks and Proto Conversion.
Regenerating and linting
Because the tree is generated, lint rules that would fire on ordinary hand-written code are turned off for it. The lint config excludes any path matching (^|/)gen/ from revive, errorlint, forbidigo and staticcheck, under the comment that generated protobuf and connect code is not ours to lint .golangci.yml. The buf.gen.yaml header points at the same exclusion as the reason the Go output lands at gen/korvus/v1/ in the first place buf.gen.yaml.
Relationships
graph LR API["api/korvus/v1 protos"] -->|"buf generate"| PBI["`gen/korvus/v1/incident.pb.go`"] API -->|"buf generate"| PBS["`gen/korvus/v1/session.pb.go`"] API -->|"buf generate"| PBSY["`gen/korvus/v1/system.pb.go`"] PBI --> CI["`gen/korvus/v1/korvusv1connect/incident.connect.go`"] PBS --> CS["`gen/korvus/v1/korvusv1connect/session.connect.go`"] PBSY --> CY["`gen/korvus/v1/korvusv1connect/system.connect.go`"] CI --> IC["`IncidentServiceClient`"] CI --> IH["`IncidentServiceHandler`"] CS --> SC["`SessionServiceClient`"] CS --> SH["`SessionServiceHandler`"] CY --> YC["`SystemServiceClient`"] CY --> YH["`SystemServiceHandler`"] IH --> MUX["transport mux in internal/transport"] SH --> MUX YH --> MUX API -->|"buf generate"| TS["gen/ts TypeScript output"]
Reference
| Symbol | Kind | What it does | Location |
|---|---|---|---|
gen/korvus/v1/incident.pb.go |
file | Protobuf messages, enums and descriptor for the incident domain | incident.pb.go |
gen/korvus/v1/session.pb.go |
file | Protobuf messages, enums and descriptor for sessions, turns, reports and artifacts | session.pb.go |
gen/korvus/v1/system.pb.go |
file | Protobuf messages for status, MCP servers, skills, templates, workspace sync and alert triggering | system.pb.go |
gen/korvus/v1/korvusv1connect/incident.connect.go |
file | Connect client/handler for korvus.v1.IncidentService |
incident.connect.go |
gen/korvus/v1/korvusv1connect/session.connect.go |
file | Connect client/handler for korvus.v1.SessionService |
session.connect.go |
gen/korvus/v1/korvusv1connect/system.connect.go |
file | Connect client/handler for korvus.v1.SystemService |
system.connect.go |
IncidentServiceClient |
interface | Client-side method set for the seven incident RPCs | incident.connect.go |
IncidentServiceHandler |
interface | Server-side method set implementing the same RPCs | incident.connect.go |
SessionServiceClient |
interface | Client-side method set for the eleven session RPCs | session.connect.go |
SessionServiceHandler |
interface | Server-side method set implementing the same RPCs | session.connect.go |
SystemServiceClient |
interface | Client-side method set for the six system RPCs | system.connect.go |
SystemServiceHandler |
interface | Server-side method set implementing the same RPCs | system.connect.go |
Generated by astrolabe from commit 0c2dca73 on branch main.