syntax = "proto3";

package nexuscrm.runtime.v1;

import "common/v1/common.proto";
import "runtime/v1/effective_permissions.proto";
import "runtime/v1/query.proto";

option go_package = "github.com/pingcap-inc/nexuscrm-contract/wire-go/gen/runtime/v1;runtimev1";

// RecordViewReadService owns one complete authorized record-view read. Product
// URL, relationship-envelope, and error grammar stay with the L1 caller.
service RecordViewReadService {
  rpc ReadRecordView(ReadRecordViewRequest) returns (ReadRecordViewResponse);
  rpc ResolveRecordAttachmentSources(ResolveRecordAttachmentSourcesRequest) returns (ResolveRecordAttachmentSourcesResponse);
}

enum RecordViewSelectorKind {
  RECORD_VIEW_SELECTOR_KIND_UNSPECIFIED = 0;
  RECORD_VIEW_SELECTOR_KIND_RECORD_ID = 1;
  RECORD_VIEW_SELECTOR_KIND_FIELD_EQUAL = 2;
}

message RecordViewSelector {
  RecordViewSelectorKind kind = 1;
  string record_id = 2;
  string field_id = 3;
  string field_value = 4;
}

enum RecordViewProjection {
  RECORD_VIEW_PROJECTION_UNSPECIFIED = 0;
  RECORD_VIEW_PROJECTION_ROOT = 1;
  RECORD_VIEW_PROJECTION_ENRICHED_VIEW = 2;
}

// Identity, tenant, AppInstallation, and authority are authenticated transport
// context. They are never caller-selected semantic request fields.
message ReadRecordViewRequest {
  string object_id = 1;
  RecordViewSelector selector = 2;
  RecordViewProjection projection = 3;
  optional uint64 min_catalog_revision = 4;
  // Selects bounded workspace result sections. Transport context is implicit.
  RecordViewWorkspaceSelection workspace = 5;
}

enum RecordViewWorkspaceSection {
  RECORD_VIEW_WORKSPACE_SECTION_UNSPECIFIED = 0;
  RECORD_VIEW_WORKSPACE_SECTION_SYSTEM_PERMISSIONS = 1;
  RECORD_VIEW_WORKSPACE_SECTION_CUSTOM_PERMISSIONS = 2;
  RECORD_VIEW_WORKSPACE_SECTION_OBJECT_PERMISSIONS = 3;
  RECORD_VIEW_WORKSPACE_SECTION_FIELD_PERMISSIONS = 4;
  RECORD_VIEW_WORKSPACE_SECTION_RECORD_TYPE_PERMISSIONS = 5;
}

message RecordViewWorkspaceSelection {
  repeated RecordViewWorkspaceSection sections = 1;
}

message RecordViewSelectedAuthority {
  repeated EffectivePermissionGrant system_permissions = 1;
  repeated EffectivePermissionGrant custom_permissions = 2;
  repeated EffectiveObjectPermission object_permissions = 3;
  repeated EffectiveFieldPermission field_permissions = 4;
  repeated EffectiveRecordTypePermission record_type_permissions = 5;
}

message RecordViewReferenceDisplay {
  string source_field_id = 1;
  string relationship_id = 2;
  string target_object_id = 3;
  string target_record_id = 4;
  string display_name = 5;
}

// Binds one authorized root string field to a closed Catalog resolver. The L1
// caller may parse its own product source grammar, but it never receives the
// resolver plan, relation names, joins, or authorization rules.
message RecordViewAttachmentSourceField {
  string source_field_id = 1;
  string resolver_id = 2;
}

// Record-scoped authority computed from the same raw row as root. This is a
// neutral result; product UI field names and envelopes remain owned by L1.
message RecordViewAccess {
  bool read = 1;
  bool update = 2;
  bool delete = 3;
  bool locked = 4;
}

message ReadRecordViewResponse {
  string record_id = 1;
  QueryRecord root = 2;
  repeated RecordViewReferenceDisplay reference_displays = 3;
  repeated RecordViewAttachmentSourceField attachment_source_fields = 4;
  nexuscrm.common.v1.ConsistencyReceipts receipts = 5;
  RecordViewAccess access = 6;
  RecordViewSelectedAuthority authority = 7;
}

message ResolveRecordAttachmentSourcesRequest {
  string parent_object_id = 1;
  string parent_record_id = 2;
  // One request selects one closed plan; resolver diversity cannot create a
  // hidden database N+1 path.
  string resolver_id = 3;
  repeated string source_values = 4;
  optional uint64 min_catalog_revision = 5;
}

enum RecordAttachmentSourceOutcome {
  RECORD_ATTACHMENT_SOURCE_OUTCOME_UNSPECIFIED = 0;
  RECORD_ATTACHMENT_SOURCE_OUTCOME_NOT_FOUND = 1;
  RECORD_ATTACHMENT_SOURCE_OUTCOME_UNAVAILABLE = 2;
  RECORD_ATTACHMENT_SOURCE_OUTCOME_RESOLVED = 3;
}

message RecordAttachmentSourceResult {
  uint32 index = 1;
  RecordAttachmentSourceOutcome outcome = 2;
  string file_id = 3;
  string file_name = 4;
}

message ResolveRecordAttachmentSourcesResponse {
  repeated RecordAttachmentSourceResult results = 1;
  nexuscrm.common.v1.ConsistencyReceipts receipts = 2;
}
