// running-process v2 broker — service definition schema.
//
// v2 supersedes the v1 service definition (`broker_v1_service_def.proto`,
// FROZEN FOREVER per #228). The v2 schema lives in its own package so the
// two coexist during rollout; consumers opt in to v2 individually.
//
// Service-definition files live in the same per-OS directories the v1
// loader uses; the v2 broker resolves them via a v2-specific extension
// (e.g. `.servicedef.v2`) so a v1 broker never reads a v2 file by mistake.
//
// This file currently introduces the `HttpServerCapability` optional
// sub-message defined in #483 plus the minimum `ServiceDefinition`
// envelope required to attach it. Additional v2 fields (version mode,
// update backend, broker port mode wiring) land in their own slices.

syntax = "proto3";
package running_process.broker.v2;

// Optional per-backend HTTP server capability.
//
// A backend declares HTTP support by setting this field on its
// `ServiceDefinition`. Absence of the field means the backend serves no
// HTTP surface; presence is the capability advertisement. v2 uses
// structured fields for capabilities rather than the v1 `u64` Hello
// bitmap (`broker/capabilities.rs`, frozen forever per #228) so new
// capabilities never collide with frozen v1 bit assignments.
//
// Port assignment is NOT carried here. The daemon binds `127.0.0.1:0`
// at startup and reports its OS-assigned port to the broker via the
// existing broker↔daemon control channel (see #483 §2). The fields
// below describe what the backend exposes once it has bound a port.
message HttpServerCapability {
  // Loopback IP the backend will bind. Default `127.0.0.1` when empty.
  // The broker enforces deploy-time bind policy (env-overridden in
  // container deployments) so backends that try to bind elsewhere
  // without authorization are still constrained by the surrounding
  // environment.
  string bind_addr = 1;

  // Health-check path served by the backend. Default `/health` when
  // empty. The aggregator polls this to gate the iframe `src` swap.
  string health_path = 2;

  // Human-readable label shown in the aggregator selector. Default to
  // the service name when empty.
  string display_name = 3;
}

// Broker isolation mode for a service.
//
// Mirrors v1's `BrokerIsolation` enum (`broker_v1_service_def.proto`)
// so v2 service definitions can carry the same trust-grouping semantics
// the v1 broker has used since #228. New isolation modes (if any) land
// here; v1's enum is FROZEN FOREVER.
enum BrokerIsolation {
  // DEFAULT - safe; private broker per service. Third-party consumers
  // get isolation automatically with zero ceremony.
  PRIVATE_BROKER = 0;

  // Opt-in to per-user shared broker. Recommended for first-party tools
  // that benefit from shared infrastructure + cross-service ops.
  SHARED_BROKER = 1;

  // Named broker instance, e.g. "ci-trusted" / "ci-untrusted" for
  // explicit trust grouping.
  EXPLICIT_INSTANCE = 2;
}

// v2 service definition envelope.
//
// Carries the service identity, the launcher / isolation policy shared
// with v1, and the new v2-only capability fields. The fields shared
// with v1 (binary_path, isolation, etc.) intentionally use the same
// field numbers as `broker_v1.ServiceDefinition` (2–8) to keep the
// human-readable diff between the two messages obvious and to make
// the v1 → v2 migration a literal field-by-field move on the consumer
// side. New v2-only fields start at 10 (http_server) and grow upward.
message ServiceDefinition {
  // [a-z0-9-]{1,64}; same validation rules as v1.
  string service_name = 1;

  // Canonical path to the backend binary. v1: `binary_path` (field 2).
  // Pre-#522 v2 brokers ignored this; consumers populating the field on
  // a pre-#522 broker get the v2 envelope round-trip but the broker
  // can't launch from the path until upgraded.
  string binary_path = 2;

  // Broker isolation mode. v1: `BrokerIsolation` (field 3). Defaults
  // to `PRIVATE_BROKER` (proto3 zero value) when absent.
  BrokerIsolation isolation = 3;

  // Used only when `isolation == EXPLICIT_INSTANCE`. v1: `explicit_instance`
  // (field 4). Ignored for other isolation modes.
  string explicit_instance = 4;

  // Canonicalized allow-list root for backends. v1: `per_version_binary_dir`
  // (field 5). The broker refuses any `binary_path` that does not resolve
  // under this directory.
  string per_version_binary_dir = 5;

  // Semver floor — broker refuses any Hello whose `wanted_version` is
  // below this. v1: `min_version` (field 6). Empty => no floor.
  string min_version = 6;

  // Optional strict pin list. v1: `version_allow_list` (field 7). When
  // non-empty, the broker refuses any Hello whose `wanted_version` is
  // not in this list. Use sparingly — `min_version` is the common case.
  repeated string version_allow_list = 7;

  // Arbitrary key/value labels (deployment hints, A/B routing tags, …).
  // v1: `labels` (field 8). Broker does not interpret these; they are
  // surfaced verbatim to consumers via the existing reflection APIs.
  map<string, string> labels = 8;

  // Optional HTTP server capability. Absent => backend serves no HTTP.
  // v2-only field; v1 has no HTTP-server concept.
  optional HttpServerCapability http_server = 10;
}
