Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/dwarves

crates/nornir-warehouse-embed/proto/workspaces.proto

// A TRIMMED copy of nornir-server's `Workspaces` control surface — ONLY the
// verbs dwarves' "Add warehouse (SSH) → Populate" affordance drives: Register
// (add + eager-populate), Fetch (re-sync), List. Package `nornir.v1` so the
// generated method paths (`/nornir.v1.Workspaces/Register` …) match the live
// `nornir-server` — dwarves speaks it as a THIN client WITHOUT linking the
// `nornir` crate (a `dwarves → nornir` edge would be a dependency cycle; the
// `nornir-funnel-embed` / telemetry pattern). Field numbers are byte-identical
// to `nornir/proto/nornir.proto` so the wire is compatible.
//
// ARCHITECTURE (amended doctrine): the warehouse is nornir's; dwarves reaches it
// by gRPC, never directly to skade. The UI ("Add warehouse…", "Populate") lives
// in dwarves; the warehouse-WRITE (clone SSH members + build the warehouse) is
// nornir's — `Register{lazy=false}` clones + builds inline, `Fetch{force}` re-syncs.
syntax = "proto3";
package nornir.v1;

service Workspaces {
  rpc List     (Empty)                    returns (WorkspaceList);
  rpc Get      (WorkspaceName)            returns (WorkspaceRecord);
  rpc Register (RegisterWorkspaceRequest) returns (WorkspaceRecord);
  // Remove — the OTHER half of the whole-action pair. `purge = true` also
  // `remove_dir_all`s the workspace's on-disk `builds/` (warehouse +
  // catalog.redb + jobs.redb), not just the registry row, so "remove" clears
  // the warehouse and everything with it rather than leaving a registered
  // entry pointing at data nobody deletes. It touches the SERVER's workspace
  // data only — it is not, and must never become, a credential operation.
  rpc Remove   (WorkspaceName)            returns (Empty);
  rpc Fetch    (WorkspaceFetchRequest)    returns (WorkspaceFetchReport);
  // PopulateStatus — the per-workspace populate ROLL-UP for the whole registry:
  // one compact `RosterRow`-shaped JSON object per workspace (name / mode /
  // members / last_synced / populate verdict / failing_member / last_error),
  // rolled up server-side from `clone_events`. Compact by design, so it can be
  // POLLED — unlike the unpaginated `Viz.CloneEvents`, which overflows the gRPC
  // decode cap on a big workspace (and is Unimplemented besides).
  rpc PopulateStatus (Empty) returns (JsonResponse);
  // Repopulate — THE ONE REFRESH, and the reason the warehouse pane needs no
  // per-pane Scan buttons. Clear-and-repopulate the DERIVED half of a served
  // workspace's warehouse through the server's OPEN handle: `purge = true` drops
  // the derived lens tables (the set is read off nornir's own lens registry, never
  // a hand list, and never a raw scan / snapshot / base table); with or without it
  // the feed chain and the lens chain are re-enqueued.
  //
  // Both refusals are NAMED. The populate gate held mid-flight ⇒
  // FAILED_PRECONDITION carrying the in-flight job id. A chain already queued at
  // this generation ⇒ an OK report whose `refusal` is set and whose `in_flight`
  // carries those job ids — the ChainQueue dedup path.
  //
  // `nornir warehouse reset` is NOT this verb: it opens `catalog.redb` itself, so
  // it refuses whenever a server is up — which is exactly when a Refresh is asked
  // for.
  rpc Repopulate (WorkspaceRepopulateRequest) returns (WorkspaceRepopulateReport);
}

// Field numbers byte-identical to nornir-wire's `nornir.proto`.
message WorkspaceRepopulateRequest {
  string name  = 1;
  bool   purge = 2;
  // `BuildWorkspace { only: Affected }` (edda b4623dc): only the members that
  // are behind and their dependents. false = every member.
  bool   affected = 3;
}

message WorkspaceRepopulateReport {
  string workspace = 1;
  bool   purged    = 2;
  repeated string dropped = 3;
  string generation = 4;
  repeated string queued = 5;
  repeated string in_flight = 6;
  string refusal = 7;
}

// Carrier for the JSON-bodied read RPCs (field number matches nornir's).
message JsonResponse { string json = 1; }

message Empty {}

// Field numbers byte-identical to nornir/proto/nornir.proto's `WorkspaceName`.
message WorkspaceName {
  string name  = 1;
  // Only honored by `Remove`: also delete the on-disk warehouse, not just the
  // registry row. Default false = registry-only.
  bool   purge = 2;
}

message RegisterWorkspaceRequest {
  string name       = 1;
  string descriptor = 2;
  string mode       = 3;   // monitored | pushed | external; default pushed
  string poll       = 4;
  // EAGER by default (lazy=false): record AND immediately clone members + build
  // the warehouse inline (the populate). lazy=true = record-only.
  bool   lazy       = 5;
  // THIN-MODE descriptor SHIP: the client reads a local `nornir-workspace.toml`
  // and ships its CONTENT here; the server writes it to its own descriptors dir
  // and registers pointing at THAT server-local path. Empty = `descriptor`
  // carries a git URL or an already-server-readable path.
  string descriptor_content = 6;
}

message WorkspaceFetchRequest {
  string name       = 1;
  bool   force      = 2;
  bool   background = 3;
}

message WorkspaceMember {
  string name          = 1;
  string remote        = 2;
  string git_ref       = 3;
  string last_seen_sha = 4;
  string last_synced   = 5;
  string sync_state    = 6;
  string worktree_digest = 7;
  bool   worktree_dirty  = 8;
}

message WorkspaceRecord {
  string name             = 1;
  string mode             = 2;
  string descriptor       = 3;
  string poll             = 4;
  string current_snapshot = 5;
  repeated WorkspaceMember members = 6;
  string created_at       = 7;
  string updated_at       = 8;
}

message WorkspaceList { repeated WorkspaceRecord workspaces = 1; }

message WorkspaceFetchReport {
  string workspace        = 1;
  uint32 fetched          = 2;
  repeated string changed = 3;
  repeated string errors  = 4;   // "member: message"
  string snapshot         = 5;   // new warehouse snapshot id if republished, else ""
}