py/facett_demo/proto/saga.proto
// SAGA — the slice of `nornir.v1` this demo speaks as a THIN producer.
//
// SOURCE OF TRUTH: `edda/crates/nornir-wire/proto/nornir.proto` (`service Saga`,
// EPIC SAGA / task #42). This file is a wire-compatible SUBSET of it — same
// package, same service name, same field numbers — so a Python producer talks to
// the running `nornir-server` without generating gencode for all 20 services.
//
// The subset is NOT allowed to drift: `py/tests/test_saga.py` re-reads the
// nornir-wire proto and fails if any field number, field type or RPC signature
// here disagrees with it. (It named a `test_saga_wire.py` that never existed —
// a pointer to an imaginary guard reads exactly like a real one.)
//
// Regenerate the stubs (korp's too, from ITS single source) with:
// python scripts/regen_protos.py
syntax = "proto3";
package nornir.v1;
message Empty {}
message SubmitCountResponse { uint32 accepted = 1; }
message JsonResponse { string json = 1; }
// One captured moment — the wire twin of `nornir_saga::SagaEvent` (all 16
// replay-relevant fields; `kind` is the lowercase tag nav|click|log|error|state).
message SagaEventPb {
uint64 seq = 1;
uint64 ts_micros = 2;
string session_id = 3;
string user = 4;
string kind = 5;
string route = 6;
string component = 7;
string action = 8;
string detail = 9;
string state_json = 10;
string level = 11;
string span_id = 12;
string parent = 13;
string app = 14;
string app_version = 15;
string git_sha = 16;
}
message RecordSagaEventsRequest {
string session_id = 1; // optional hint; each event carries its own
repeated SagaEventPb events = 2;
}
message SagaSessionQuery { string session_id = 1; }
message SagaEventList { repeated SagaEventPb events = 1; }
service Saga {
// Land a producer's captured events into the warehouse. Ack = count accepted
// (SubmitCountResponse) so a caller can detect a partial/rejected batch.
rpc RecordEvents (RecordSagaEventsRequest) returns (SubmitCountResponse);
// The painful-first Sessions roll-up, as a JSON array of SagaSessionSummary.
rpc ListSessions (Empty) returns (JsonResponse);
// One session's events, scoped + seq-ordered, for replay.
rpc ReadSession (SagaSessionQuery) returns (SagaEventList);
}