syntax = "proto3";

package nexuscrm.runtime.v1;

import "common/v1/common.proto";

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

// RecordAttachmentSourceResolutionService resolves product-parsed attachment
// sources only after Runtime verifies the exact authorized parent-field proof.
// Source grammar, URLs, tables, joins, and authorization rules are never wire
// facts.
service RecordAttachmentSourceResolutionService {
  rpc ResolveAttachmentSources(ResolveAttachmentSourcesRequest) returns (ResolveAttachmentSourcesResponse);
}

// AttachmentSourceProof binds one parsed value to its exact byte offset in one
// current parent-field value. Runtime verifies this proof after CRUD, RLS, and
// FLS enforcement and before source lookup.
message AttachmentSourceProof {
  string source_field_id = 1;
  string source_value = 2;
  uint32 source_value_offset = 3;
}

// Identity, tenant, AppInstallation, and authority are authenticated transport
// context. They are never caller-selected semantic request fields.
message ResolveAttachmentSourcesRequest {
  string parent_object_id = 1;
  string parent_record_id = 2;
  string resolver_id = 3;
  repeated AttachmentSourceProof sources = 4;
  optional uint64 min_catalog_revision = 5;
}

enum AttachmentSourceResolutionOutcome {
  ATTACHMENT_SOURCE_RESOLUTION_OUTCOME_UNSPECIFIED = 0;
  ATTACHMENT_SOURCE_RESOLUTION_OUTCOME_NOT_FOUND = 1;
  ATTACHMENT_SOURCE_RESOLUTION_OUTCOME_UNAVAILABLE = 2;
  ATTACHMENT_SOURCE_RESOLUTION_OUTCOME_RESOLVED = 3;
}

// Only RESOLVED carries authorized file facts. UNAVAILABLE deliberately does
// not disclose whether proof, source-row, or file authorization caused denial.
message AttachmentSourceResolutionResult {
  uint32 index = 1;
  AttachmentSourceResolutionOutcome outcome = 2;
  string file_id = 3;
  string file_name = 4;
}

message ResolveAttachmentSourcesResponse {
  repeated AttachmentSourceResolutionResult results = 1;
  nexuscrm.common.v1.ConsistencyReceipts receipts = 2;
}
