// Common types shared across every TARS service.
//
// Defines the cross-cutting vocabulary every other proto package reuses:
// typed-ID prefix registry, cursor pagination shape, the idempotency-key
// wrapper, and the RFC 7807 problem-detail error envelope.
//
// Adopted from IA's common.v1 to keep wire shapes congruent across the two
// platforms. See plan: check-ia-and-plan-optimized-cook.md item A3.
syntax = "proto3";

package tars.common.v1;

import "google/api/field_behavior.proto";

option go_package = "github.com/tetrateio/fraser/api/tars/common/v1;commonv1";

// IdPrefix enumerates the closed set of resource-id prefixes used by TARS.
//
// Every TARS identifier on the wire is a string of the form `{prefix}_{ULID}`,
// for example `cust_01H...`, `proj_01H...`, `op_01H...`. The prefix makes IDs
// human-distinguishable in logs and curl examples; the ULID makes them
// time-ordered and globally unique.
//
// The registry is closed: introducing a new prefix is a versioned change to
// this enum. Removing a value is breaking. Append-only.
enum IdPrefix {
  ID_PREFIX_UNSPECIFIED = 0;

  // cust_ -- Customer (top-level tenant).
  ID_PREFIX_CUSTOMER = 1;

  // proj_ -- Project (per-customer isolation unit for routes, BYOK, budgets).
  ID_PREFIX_PROJECT = 2;

  // dp_ -- Dataplane (a managed inference data-plane instance).
  ID_PREFIX_DATAPLANE = 3;

  // key_ -- API key issued to an identity.
  ID_PREFIX_API_KEY = 4;

  // op_ -- Long-running Operation.
  ID_PREFIX_OPERATION = 5;

  // id_ -- Identity (human user, service account, or machine principal).
  ID_PREFIX_IDENTITY = 6;

  // bdg_ -- Budget attached to a project.
  ID_PREFIX_BUDGET = 7;

  // byok_ -- Bring-Your-Own-Key material handle.
  ID_PREFIX_BYOK_KEY = 8;

  // gw_ -- Gateway (physical runtime endpoint owning one customer-facing
  // invocation URL).
  ID_PREFIX_GATEWAY = 9;

  // pgm_ -- ProjectGatewayMap (1:1 binding between a project and a
  // gateway in v1; relaxes to 1:N in a future major version).
  ID_PREFIX_PROJECT_GATEWAY_MAP = 10;

  // dpc_ -- DataplaneCredential (DP to MP service-account JWT).
  ID_PREFIX_DATAPLANE_CREDENTIAL = 11;

  // prov_ -- Catalog provider (e.g. OpenAI, Anthropic, AWS Bedrock).
  ID_PREFIX_PROVIDER = 12;

  // mdl_ -- Catalog model (logical name bound to a provider).
  ID_PREFIX_MODEL = 13;

  // plan_ -- Billing plan (subscription tier).
  ID_PREFIX_BILLING_PLAN = 14;

  // usage_ -- Usage record (per-request cost accounting row).
  ID_PREFIX_USAGE_RECORD = 15;

  // sess_ -- Browser session JWT.
  ID_PREFIX_SESSION = 16;

  // wh_ -- Webhook subscription.
  ID_PREFIX_WEBHOOK = 17;
}

// PageRequest carries the standard cursor-pagination inputs.
//
// List RPCs may either embed this message directly or inline the equivalent
// fields with the same field numbers. Pagination is opaque-cursor only;
// offset-based paging is not supported.
message PageRequest {
  // Maximum items the server should return. The server may cap this; default
  // page size and cap are documented per-RPC. Zero means "use server default".
  int32 page_size = 1;

  // Continuation token returned by a prior PageResponse.next_page_token.
  // Treat as opaque; clients MUST NOT decode or construct one.
  string page_token = 2;

  // Optional server-side filter expression (AIP-160 syntax). Empty means
  // "no filter".
  string filter = 3;

  // Optional sort expression, e.g. `created_at desc`. Empty means
  // "server default order".
  string order_by = 4;
}

// PageResponse carries the standard cursor-pagination outputs.
//
// List RPCs may embed this message or inline the equivalent field. Empty
// next_page_token means there are no further pages.
message PageResponse {
  // Continuation token to pass as PageRequest.page_token on the next call.
  // Empty when the listing is exhausted.
  string next_page_token = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
}

// IdempotencyKey wraps a caller-generated key for safe retry of mutating
// requests.
//
// The canonical pattern is to inline a `string idempotency_key = 99` field
// on each mutating request message. This wrapper exists so SDK helpers and
// middleware can pass the key around as a typed value without
// re-stringifying it.
message IdempotencyKey {
  // The caller-generated key. Recommended format is a UUIDv4 or ULID.
  string value = 1 [(google.api.field_behavior) = REQUIRED];
}

// Problem is the RFC 7807 problem-detail envelope TARS returns for all error
// responses on the wire.
//
// On the JSON / REST surface, errors serialize as `application/problem+json`
// with these fields. On the gRPC surface, errors are returned as
// `google.rpc.Status` with typed details (ErrorInfo, BadRequest, etc.); the
// facade projects them into this Problem shape for HTTP clients.
//
// Field numbers 1-5 mirror RFC 7807 section 3.1 exactly. Field numbers 10+
// carry TARS-specific extension members surfaced from
// `google.rpc.ErrorInfo` and trace context.
message Problem {
  // URI reference identifying the problem type. Defaults to `about:blank`
  // when no specific type is registered. SHOULD resolve to human-readable
  // documentation when dereferenced.
  string type = 1 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Short, human-readable summary of the problem type. SHOULD NOT change
  // between occurrences except for localization.
  string title = 2 [(google.api.field_behavior) = OUTPUT_ONLY];

  // HTTP status code generated by the origin server for this occurrence.
  int32 status = 3 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Human-readable explanation specific to this occurrence of the problem.
  string detail = 4 [(google.api.field_behavior) = OUTPUT_ONLY];

  // URI reference identifying the specific occurrence of the problem.
  // Often a URL the support team can use to look up the request.
  string instance = 5 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Machine-readable error reason in SCREAMING_SNAKE_CASE. Mirrors
  // `google.rpc.ErrorInfo.reason`. Examples: `BUDGET_EXCEEDED`,
  // `STEP_UP_REQUIRED`, `BYOK_KEY_DISABLED`.
  string reason = 10 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Operator domain that emitted the error, e.g. `tetrate.ai`. Filled in by
  // the facade from operator-config; never hardcoded by services.
  string domain = 11 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Additional structured context for the error. Keys are stable
  // identifiers (e.g., `field`, `quota_metric`, `retry_after_seconds`);
  // values are human-readable strings or stringified scalars.
  map<string, string> metadata = 12 [(google.api.field_behavior) = OUTPUT_ONLY];

  // W3C trace ID for correlating this error with server-side observability.
  // Echoed from the inbound `traceparent` header when present.
  string trace_id = 13 [(google.api.field_behavior) = OUTPUT_ONLY];
}
