Some checks failed
Proto CI / lint (push) Has been cancelled
Add GovernanceEnvelope proto message and embed it in GetCanonicalHeadResponse, CommitResponse, and MergeToCanonicalResponse. The envelope carries the git ref, actor DID, accord hash, and ceremony ID so consumers can forward governance context to Chronicle and Quartermaster without reconstructing it. Wire-compatible: the envelope field is optional (proto3 default), so existing consumers that don't read it are unaffected. Signed-off-by: Tyler King <tking@guildhouse.dev>
454 lines
12 KiB
Protocol Buffer
454 lines
12 KiB
Protocol Buffer
syntax = "proto3";
|
|
package workspace.v1;
|
|
|
|
import "google/protobuf/timestamp.proto";
|
|
|
|
service WorkspaceController {
|
|
// Initialize the canonical repository (first-time setup)
|
|
rpc InitCanonical(InitCanonicalRequest) returns (InitCanonicalResponse);
|
|
|
|
// Get canonical repo status
|
|
rpc GetCanonicalHead(GetCanonicalHeadRequest) returns (GetCanonicalHeadResponse);
|
|
|
|
// Session workspace lifecycle
|
|
rpc CreateWorkspace(CreateWorkspaceRequest) returns (CreateWorkspaceResponse);
|
|
rpc GetWorkspaceStatus(GetWorkspaceStatusRequest) returns (GetWorkspaceStatusResponse);
|
|
rpc DestroyWorkspace(DestroyWorkspaceRequest) returns (DestroyWorkspaceResponse);
|
|
|
|
// Diff and commit
|
|
rpc GetDiff(GetDiffRequest) returns (GetDiffResponse);
|
|
rpc StageFiles(StageFilesRequest) returns (StageFilesResponse);
|
|
rpc Commit(CommitRequest) returns (CommitResponse);
|
|
rpc GetLog(GetLogRequest) returns (GetLogResponse);
|
|
|
|
// Abandon (discard all changes)
|
|
rpc Abandon(AbandonRequest) returns (AbandonResponse);
|
|
|
|
// List active workspaces
|
|
rpc ListWorkspaces(ListWorkspacesRequest) returns (ListWorkspacesResponse);
|
|
|
|
// Get a tar archive of the canonical repo at a specific commit
|
|
rpc GetArchive(GetArchiveRequest) returns (stream ArchiveChunk);
|
|
|
|
// --- Remote sync (Phase 3) ---
|
|
|
|
// Push canonical branch to a configured remote
|
|
rpc PushToRemote(PushToRemoteRequest) returns (PushToRemoteResponse);
|
|
|
|
// Fetch refs from a configured remote into inbound/ branches
|
|
rpc FetchFromRemote(FetchFromRemoteRequest) returns (FetchFromRemoteResponse);
|
|
|
|
// List configured remotes from .guildhouse/remotes.yaml
|
|
rpc ListRemotes(ListRemotesRequest) returns (ListRemotesResponse);
|
|
|
|
// Get sync status between canonical and a remote
|
|
rpc GetRemoteSyncStatus(GetRemoteSyncStatusRequest) returns (GetRemoteSyncStatusResponse);
|
|
|
|
// Report commit status check to a remote provider (GitHub/Forgejo/GitLab)
|
|
rpc ReportStatus(ReportStatusRequest) returns (ReportStatusResponse);
|
|
|
|
// --- Merge operations (Phase 4) ---
|
|
|
|
// Merge an inbound branch into canonical main
|
|
rpc MergeToCanonical(MergeToCanonicalRequest) returns (MergeToCanonicalResponse);
|
|
|
|
// Clean up an inbound branch after merge or rejection
|
|
rpc CleanupInboundBranch(CleanupInboundBranchRequest) returns (CleanupInboundBranchResponse);
|
|
|
|
// List inbound branches (fetched from remotes)
|
|
rpc ListInboundBranches(ListInboundBranchesRequest) returns (ListInboundBranchesResponse);
|
|
|
|
// Lightweight remote HEAD check (ls-remote equivalent — no objects fetched)
|
|
rpc LsRemote(LsRemoteRequest) returns (LsRemoteResponse);
|
|
}
|
|
|
|
// --- Governance Envelope ---
|
|
// Binds a git ref to governance metadata (actor, accord, ceremony).
|
|
// Propagated in responses so consumers can forward to Chronicle
|
|
// and Quartermaster without reconstructing context.
|
|
|
|
message GovernanceEnvelope {
|
|
// Git object hash (20 bytes SHA-1, hex-encoded = 40 chars)
|
|
string git_ref = 1;
|
|
// "commit", "tree", or "blob"
|
|
string git_ref_type = 2;
|
|
// Branch or tag ref name (e.g. "refs/heads/main")
|
|
string git_ref_name = 3;
|
|
// Repository identifier (e.g. "guildhouse/substrate")
|
|
string repository = 4;
|
|
// SHA-256 of the governing accord (hex-encoded = 64 chars)
|
|
string accord_hash = 5;
|
|
// Actor DID (e.g. "did:web:guildhouse.dev:user:tking")
|
|
string actor_did = 6;
|
|
// Nanoseconds since Unix epoch
|
|
uint64 timestamp_ns = 7;
|
|
// Ceremony ID if approval was required
|
|
string ceremony_id = 8;
|
|
}
|
|
|
|
// --- Canonical ---
|
|
|
|
message InitCanonicalRequest {
|
|
// Path to a directory of manifests to import as the initial commit.
|
|
// If empty, creates an empty repo with just .guildhouse/ structure.
|
|
string import_path = 1;
|
|
// Commit author
|
|
string author = 2;
|
|
}
|
|
|
|
message InitCanonicalResponse {
|
|
string commit_hash = 1;
|
|
string message = 2;
|
|
}
|
|
|
|
message GetCanonicalHeadRequest {}
|
|
|
|
message GetCanonicalHeadResponse {
|
|
string commit_hash = 1;
|
|
string message = 2;
|
|
string author = 3;
|
|
google.protobuf.Timestamp timestamp = 4;
|
|
uint32 total_files = 5;
|
|
// Governance envelope for the HEAD commit
|
|
GovernanceEnvelope envelope = 6;
|
|
}
|
|
|
|
// --- Session workspace lifecycle ---
|
|
|
|
message CreateWorkspaceRequest {
|
|
string session_id = 1;
|
|
// Branch to base the workspace on (default: "main")
|
|
string base_branch = 2;
|
|
// Git author for commits in this workspace
|
|
string author_name = 3;
|
|
string author_email = 4;
|
|
// If true, workspace is read-only (no branch created, just a checkout)
|
|
bool read_only = 5;
|
|
}
|
|
|
|
message CreateWorkspaceResponse {
|
|
// Filesystem path to the workspace root
|
|
string workspace_path = 1;
|
|
// Git branch name (empty if read_only)
|
|
string branch_name = 2;
|
|
// SHA of the base commit
|
|
string base_commit = 3;
|
|
}
|
|
|
|
message GetWorkspaceStatusRequest {
|
|
string session_id = 1;
|
|
}
|
|
|
|
message GetWorkspaceStatusResponse {
|
|
string session_id = 1;
|
|
string branch_name = 2;
|
|
string base_commit = 3;
|
|
string head_commit = 4;
|
|
uint32 commits_ahead = 5;
|
|
uint32 files_changed = 6;
|
|
uint32 insertions = 7;
|
|
uint32 deletions = 8;
|
|
bool has_uncommitted_changes = 9;
|
|
bool read_only = 10;
|
|
}
|
|
|
|
message DestroyWorkspaceRequest {
|
|
string session_id = 1;
|
|
}
|
|
|
|
message DestroyWorkspaceResponse {
|
|
bool success = 1;
|
|
string message = 2;
|
|
}
|
|
|
|
// --- Diff and commit ---
|
|
|
|
message GetDiffRequest {
|
|
string session_id = 1;
|
|
// If true: diff uncommitted changes only (workspace vs HEAD)
|
|
// If false: diff entire branch vs base (session branch vs main)
|
|
bool uncommitted_only = 2;
|
|
}
|
|
|
|
message GetDiffResponse {
|
|
repeated FileDiff files = 1;
|
|
string base_ref = 2;
|
|
string head_ref = 3;
|
|
uint32 total_insertions = 4;
|
|
uint32 total_deletions = 5;
|
|
}
|
|
|
|
message FileDiff {
|
|
string path = 1;
|
|
// "added", "modified", "deleted", "renamed"
|
|
string status = 2;
|
|
// Unified diff text (empty for binary files)
|
|
string diff_text = 3;
|
|
uint32 insertions = 4;
|
|
uint32 deletions = 5;
|
|
// For renames: the old path
|
|
string old_path = 6;
|
|
}
|
|
|
|
message StageFilesRequest {
|
|
string session_id = 1;
|
|
// File paths to stage (relative to workspace root).
|
|
// Empty = stage all changes (git add -A).
|
|
repeated string paths = 2;
|
|
}
|
|
|
|
message StageFilesResponse {
|
|
uint32 files_staged = 1;
|
|
}
|
|
|
|
message CommitRequest {
|
|
string session_id = 1;
|
|
string message = 2;
|
|
// Override author (if empty, uses the author from CreateWorkspace)
|
|
string author_name = 3;
|
|
string author_email = 4;
|
|
}
|
|
|
|
message CommitResponse {
|
|
string commit_hash = 1;
|
|
uint32 files_committed = 2;
|
|
string message = 3;
|
|
// Governance envelope for the new commit
|
|
GovernanceEnvelope envelope = 4;
|
|
}
|
|
|
|
message GetLogRequest {
|
|
string session_id = 1;
|
|
// Max number of commits to return (default: 20)
|
|
uint32 limit = 2;
|
|
}
|
|
|
|
message GetLogResponse {
|
|
repeated CommitEntry commits = 1;
|
|
}
|
|
|
|
message CommitEntry {
|
|
string hash = 1;
|
|
string short_hash = 2;
|
|
string message = 3;
|
|
string author_name = 4;
|
|
string author_email = 5;
|
|
google.protobuf.Timestamp timestamp = 6;
|
|
uint32 files_changed = 7;
|
|
}
|
|
|
|
// --- Abandon ---
|
|
|
|
message AbandonRequest {
|
|
string session_id = 1;
|
|
}
|
|
|
|
message AbandonResponse {
|
|
bool success = 1;
|
|
uint32 commits_discarded = 2;
|
|
string message = 3;
|
|
}
|
|
|
|
// --- List workspaces ---
|
|
|
|
message ListWorkspacesRequest {}
|
|
|
|
message ListWorkspacesResponse {
|
|
repeated WorkspaceSummary workspaces = 1;
|
|
}
|
|
|
|
message WorkspaceSummary {
|
|
string session_id = 1;
|
|
string branch_name = 2;
|
|
string base_commit = 3;
|
|
string head_commit = 4;
|
|
uint32 commits_ahead = 5;
|
|
bool has_uncommitted_changes = 6;
|
|
bool read_only = 7;
|
|
google.protobuf.Timestamp created_at = 8;
|
|
}
|
|
|
|
// --- Archive ---
|
|
|
|
message GetArchiveRequest {
|
|
// Commit hash to archive (empty = HEAD)
|
|
string commit_hash = 1;
|
|
// Subset of paths to include (empty = all files)
|
|
repeated string paths = 2;
|
|
}
|
|
|
|
message ArchiveChunk {
|
|
bytes data = 1;
|
|
}
|
|
|
|
// --- Remote sync ---
|
|
|
|
message PushToRemoteRequest {
|
|
// Name of the remote (must exist in .guildhouse/remotes.yaml)
|
|
string remote_name = 1;
|
|
// Local branch to push (default: "main")
|
|
string branch = 2;
|
|
// Force push — always false in Phase 3
|
|
bool force = 3;
|
|
}
|
|
|
|
message PushToRemoteResponse {
|
|
bool success = 1;
|
|
// Remote ref that was updated (e.g. "refs/heads/main")
|
|
string remote_ref = 2;
|
|
// Commit hash that was pushed
|
|
string commit_hash = 3;
|
|
string error = 4;
|
|
}
|
|
|
|
message FetchFromRemoteRequest {
|
|
// Name of the remote (must exist in .guildhouse/remotes.yaml)
|
|
string remote_name = 1;
|
|
// Ref patterns to fetch (e.g. "refs/pull/*/head").
|
|
// If empty, uses fetch_refs from remotes.yaml config.
|
|
repeated string ref_patterns = 2;
|
|
}
|
|
|
|
message FetchFromRemoteResponse {
|
|
repeated FetchedRef refs_fetched = 1;
|
|
string error = 2;
|
|
}
|
|
|
|
message FetchedRef {
|
|
// Local ref name (e.g. "inbound/github-origin/pull/42/head")
|
|
string ref_name = 1;
|
|
// Commit hash at the tip of this ref
|
|
string commit_hash = 2;
|
|
// True if this is a newly fetched ref (not previously seen)
|
|
bool is_new = 3;
|
|
}
|
|
|
|
message ListRemotesRequest {}
|
|
|
|
message ListRemotesResponse {
|
|
repeated RemoteInfo remotes = 1;
|
|
}
|
|
|
|
message RemoteInfo {
|
|
string name = 1;
|
|
string url = 2;
|
|
// "github", "forgejo", or "gitlab"
|
|
string provider = 3;
|
|
string push_branch = 4;
|
|
// Last commit hash successfully pushed to this remote (empty if never pushed)
|
|
string last_push_hash = 5;
|
|
// Last time a fetch was performed from this remote
|
|
google.protobuf.Timestamp last_fetch_time = 6;
|
|
}
|
|
|
|
message GetRemoteSyncStatusRequest {
|
|
string remote_name = 1;
|
|
}
|
|
|
|
message GetRemoteSyncStatusResponse {
|
|
string remote_name = 1;
|
|
string canonical_head = 2;
|
|
string remote_head = 3;
|
|
uint32 commits_ahead = 4;
|
|
uint32 commits_behind = 5;
|
|
google.protobuf.Timestamp last_push = 6;
|
|
google.protobuf.Timestamp last_fetch = 7;
|
|
}
|
|
|
|
message ReportStatusRequest {
|
|
// Name of the remote (determines provider + credentials)
|
|
string remote_name = 1;
|
|
// Commit SHA to report status for
|
|
string commit_hash = 2;
|
|
// Status state: "pending", "success", "failure", "error"
|
|
string state = 3;
|
|
// Context label (e.g. "guildhouse/pipeline")
|
|
string context = 4;
|
|
// Human-readable description
|
|
string description = 5;
|
|
// URL to link to (e.g. pipeline run URL)
|
|
string target_url = 6;
|
|
// Attestation hash (hex-encoded) to include in description
|
|
string attestation_hash = 7;
|
|
}
|
|
|
|
message ReportStatusResponse {
|
|
bool success = 1;
|
|
// URL of the created status check (provider-specific)
|
|
string url = 2;
|
|
string error = 3;
|
|
}
|
|
|
|
// --- Merge operations ---
|
|
|
|
message MergeToCanonicalRequest {
|
|
// Branch name to merge (e.g. "inbound/github-origin/pull/42/head")
|
|
string branch_name = 1;
|
|
// Merge commit message
|
|
string merge_message = 2;
|
|
// Author for the merge commit
|
|
string author_name = 3;
|
|
string author_email = 4;
|
|
// Ceremony ID if the merge was approved via Accord
|
|
string ceremony_id = 5;
|
|
}
|
|
|
|
message MergeToCanonicalResponse {
|
|
bool success = 1;
|
|
// New HEAD commit hash after merge
|
|
string new_head = 2;
|
|
// "fast_forward" or "merge_commit"
|
|
string merge_type = 3;
|
|
// Error message (empty on success)
|
|
string error = 4;
|
|
// Number of files changed in the merge
|
|
uint32 files_changed = 5;
|
|
// Governance envelope for the merge commit
|
|
GovernanceEnvelope envelope = 6;
|
|
}
|
|
|
|
message CleanupInboundBranchRequest {
|
|
// Branch name to clean up
|
|
string branch_name = 1;
|
|
}
|
|
|
|
message CleanupInboundBranchResponse {
|
|
bool success = 1;
|
|
string message = 2;
|
|
}
|
|
|
|
message ListInboundBranchesRequest {
|
|
// Optional: filter by remote name
|
|
string remote_name = 1;
|
|
}
|
|
|
|
message ListInboundBranchesResponse {
|
|
repeated InboundBranchInfo branches = 1;
|
|
}
|
|
|
|
message InboundBranchInfo {
|
|
string branch_name = 1;
|
|
string commit_hash = 2;
|
|
string remote_name = 3;
|
|
// Original ref (e.g. "pull/42/head")
|
|
string original_ref = 4;
|
|
}
|
|
|
|
// --- Lightweight remote ref check ---
|
|
|
|
message LsRemoteRequest {
|
|
// Name of the remote
|
|
string remote_name = 1;
|
|
// Ref patterns to query (e.g. "refs/heads/main")
|
|
repeated string refs = 2;
|
|
}
|
|
|
|
message LsRemoteResponse {
|
|
repeated RemoteRef refs = 1;
|
|
string error = 2;
|
|
}
|
|
|
|
message RemoteRef {
|
|
string ref_name = 1;
|
|
string commit_hash = 2;
|
|
}
|