// Proposed contract, version 1. Status: proposal for review, not confirmed design.
//
// How model outputs enter the canonical data: as observations or events with a ComputedSourceOrigin, the model and
// its version as origin version, and a derivation that names the exact input revisions, under one WriteCommit of kind
// computation that references the ModelRun.
// Callers: ai-model-platform (batch scoring writes predictions back; req 19.*.4, 57, 61, 62).
// Deadline: 60 s per stream; a batch opens one stream per farm.
// The callers listed are authentication only (decided 2026-11-11): each RPC below names who may call it and what
// it sees, and refuses anyone else with PERMISSION_DENIED.
// x-moonitoring-callers: ai-model-platform
// x-moonitoring-requirements: 19.*.4, 57, 61, 62
syntax = "proto3";

package moonitoring.farm.observations.v1;

import "google/protobuf/timestamp.proto";

service ComputedRecordsService {
  // Appends computed observations and events for one farm under one WriteCommit. The stream is committed when it
  // closes cleanly and rolled back otherwise; a record identical to the last revision produces no new revision.
  // Callers: ai-model-platform only. Sees: only its commit; it writes only computed records of a ModelRun it
  // started.
  rpc AppendComputedRecords(stream AppendComputedRecordsRequest) returns (AppendComputedRecordsResponse);
}

message AppendComputedRecordsRequest {
  oneof payload {
    // Sent once, first.
    Header header = 1;
    ComputedObservation observation = 2;
    ComputedEvent event = 3;
  }
}

message Header {
  string request_id = 1;
  string farm_id = 2;
  // The ModelRun the records come from (ai-model-platform).
  string model_run_id = 3;
  // The write number the model read; inputs must be at or below it.
  int64 data_seq = 4;
  // The ComputedSourceOrigin and its OriginVersion (the model and its version).
  string origin_version_id = 5;
}

message ComputedObservation {
  // Exactly one subject.
  string animal_id = 1;
  string animal_group_id = 2;
  string observation_type_id = 3;
  // ObservationTime as JSON, as defined in the shared types.
  string time_json = 4;
  // ObservationValue as JSON.
  string value_json = 5;
  string context_id = 6;
  // Stable key of this output within the model run, so a replay produces no duplicate.
  string source_record_key = 7;
  Derivation derivation = 8;
}

message ComputedEvent {
  string animal_id = 1;
  string animal_group_id = 2;
  // The CanonicalEvent subtype, e.g. HeatEvent.
  string event_type = 3;
  // EventTime as JSON.
  string occurred_json = 4;
  // The typed fields of the subtype as JSON.
  string fields_json = 5;
  string source_record_key = 6;
  Derivation derivation = 7;
}

message Derivation {
  // CodedValue as JSON: the transformation, with its version.
  string transformation_json = 1;
  // Exact revisions the output was computed from.
  repeated RecordReference inputs = 2;
  string parameters_json = 3;
  google.protobuf.Timestamp computed_at = 4;
}

message RecordReference {
  // observation, event, session, resolved_event, period, animal_link, sample, product_material, ...
  string entity_kind = 1;
  string revision_id = 2;
}

message AppendComputedRecordsResponse {
  // The WriteCommit that made the records available.
  int64 write_seq = 1;
  int32 observations_written = 2;
  int32 events_written = 3;
  // Records identical to their last revision.
  int32 unchanged = 4;
}
