syntax = "proto3";

package tars.lookup.v1;

import "buf/validate/validate.proto";
import "google/api/annotations.proto";
import "google/protobuf/timestamp.proto";
import "tars/auth/v1/auth_options.proto";
import "tars/docs/v1/docs.proto";

// LookupService provides cached lookup operations for authorization and resource validation.
// Designed for high-performance scenarios like ext_authz with aggressive caching (5min TTL).
//
// Doc-internal but NOT runtime-internal: the (tars.docs.v1.internal) marker
// keeps this service out of the customer API reference, while the per-RPC
// auth annotations still accept both SERVICE_ACCOUNT (corporate dataplane
// with a mounted SA file) and API_KEY (SaaS dataplane authenticating with
// VALET_API_KEY). Doc visibility is decoupled from runtime auth so SaaS
// ext-authz keeps working without leaking the service into customer docs.
service LookupService {
  option (tars.docs.v1.internal) = true;

  // GetMCPProfileByURL retrieves an MCP profile by its URL.
  // Aggressively cached for ext_authz performance in the dataplane.
  //
  // Accepts both SERVICE_ACCOUNT (corporate dataplane with mounted SA file)
  // and API_KEY (SaaS dataplane authenticating with VALET_API_KEY). Without
  // API_KEY, SaaS dataplanes whose GetAuthToken returns a raw API key
  // (not a JWT) cannot authenticate at all. Kept out of the customer
  // reference by the service-level (tars.docs.v1.internal) marker.
  rpc GetMCPProfileByURL(GetMCPProfileByURLRequest) returns (GetMCPProfileByURLResponse) {
    option (google.api.http) = {get: "/lookup/v1/mcp-profiles/by-url"};
    option idempotency_level = NO_SIDE_EFFECTS;
    option (tars.auth.v1.auth) = {
      auth_types: [
        AUTH_TYPE_SERVICE_ACCOUNT,
        AUTH_TYPE_API_KEY
      ]
      scopes: ["read"]
    };
  }

  // ResolveRouteIdentityByKey resolves effective route identity for an authenticated key.
  // Mapping-aware behavior:
  // - mapped key => effective client UUID as tars_id
  // - unmapped key => key UUID (jti) as tars_id
  rpc ResolveRouteIdentityByKey(ResolveRouteIdentityByKeyRequest) returns (ResolveRouteIdentityByKeyResponse) {
    option (google.api.http) = {get: "/lookup/v1/route-identity/by-key"};
    option idempotency_level = NO_SIDE_EFFECTS;
    option (tars.auth.v1.auth) = {
      auth_types: [
        AUTH_TYPE_SERVICE_ACCOUNT,
        AUTH_TYPE_API_KEY
      ]
      scopes: ["read"]
    };
  }
}

// GetMCPProfileByURL

message GetMCPProfileByURLRequest {
  // URL of the MCP profile (e.g., "/mcp/profile-123")
  string url = 1 [(buf.validate.field).string.min_len = 1];

  // User token (sk-...) to validate ownership of the MCP profile.
  // Optional: when empty, the lookup returns the profile by URL only
  // (public-by-URL fetch; the caller is expected to have verified the
  // token and to enforce ownership locally — see lookup.go:88-127 and
  // tars-dataplane MCP ext_authz local-verify path). MP performs full
  // token verification + ownership check when present.
  string user_token = 2;
}

message GetMCPProfileByURLResponse {
  // MCP profile information, or null if not found
  MCPProfile profile = 1;
}

// MCPProfile represents an MCP profile configuration
message MCPProfile {
  string id = 1;
  string owner = 2;
  string name = 3;
  string description = 4;
  string url = 5;
  string status = 6;
  string error_message = 7;

  string security_policy_type = 8;
  string security_policy_value = 9;

  google.protobuf.Timestamp created_at = 10;
  google.protobuf.Timestamp updated_at = 11;
}

message ResolveRouteIdentityByKeyRequest {
  string user_id = 1 [(buf.validate.field).string.min_len = 1];
  string key_id = 2 [(buf.validate.field).string.min_len = 1];
}

message ResolveRouteIdentityByKeyResponse {
  string effective_client_id = 1;
  string route_owner_id = 2;
  string route_owner_hash = 3;
  string tars_id = 4;
  bool is_mapped_client = 5;
}
