From 3ee189dbe358b8224def090dab888fbdecbc5a42 Mon Sep 17 00:00:00 2001 From: Lukas Bindreiter Date: Mon, 9 Nov 2026 15:43:36 +0100 Subject: [PATCH] Simplify and relax documented constraints --- apis/datasets/v1/data_access.proto | 5 ---- apis/datasets/v1/dataset_type.proto | 10 +++----- apis/workflows/v1/core.proto | 6 ++--- apis/workflows/v1/resource.proto | 40 ++++++++++++++--------------- apis/workflows/v1/workflows.proto | 11 ++++---- 5 files changed, 30 insertions(+), 42 deletions(-) diff --git a/apis/datasets/v1/data_access.proto b/apis/datasets/v1/data_access.proto index ea470d1..703b079 100644 --- a/apis/datasets/v1/data_access.proto +++ b/apis/datasets/v1/data_access.proto @@ -47,11 +47,6 @@ message QueryFilters { // Additional expressions over fields marked queryable in the dataset schema. // All top-level expressions are combined with each other and with the interval and spatial filters using logical AND. // Use a nested LogicalExpression for explicit OR, NOT, or grouped boolean logic. - // Protovalidate limits each list of expressions to 64 items. Before compiling a query, the server must also enforce: - // - at most 256 FilterExpression nodes in total across all top-level and nested expressions; - // - a maximum expression depth of 8, where a top-level FilterExpression has depth 1 and each nested operand adds 1; - // - every referenced field exists and is marked queryable; and - // - every comparison operator and literal kind is valid for the referenced field's descriptor. repeated FilterExpression expressions = 4 [(buf.validate.field).repeated.max_items = 64]; } diff --git a/apis/datasets/v1/dataset_type.proto b/apis/datasets/v1/dataset_type.proto index 8c38c4d..59fb756 100644 --- a/apis/datasets/v1/dataset_type.proto +++ b/apis/datasets/v1/dataset_type.proto @@ -49,7 +49,7 @@ enum FieldRole { // EnumValue is one allowed value of a custom enum. message EnumValue { - // The value users ingest, query, and receive, e.g. "L1", limited to 128 Unicode code points. + // The value users ingest, query, and receive, e.g. "L1". string value = 1 [(buf.validate.field).string = { min_len: 1 max_len: 128 @@ -65,9 +65,7 @@ message FieldAnnotation { // This allows flattened dataset fields to be reconstructed without relying on their protobuf field names. string source_json_pointer = 3 [features.field_presence = EXPLICIT]; - // Whether the field is projected into query storage and may be used in server-side filter expressions. - // Queryable fields are not necessarily backed by a secondary database index. - // Enum fields do not count toward the queryable string field limit. + // Whether the field can be used in server-side filter expressions. bool queryable = 4; // Optional JSON Schema reference for this field when it corresponds to a well known schema. @@ -84,7 +82,7 @@ message FieldAnnotation { } ]; - // Allowed values for a custom enum field. Values must be unique, with at most 100 entries; leave empty for other types. + // Allowed values for a custom enum field. Values must be unique; leave empty for other types. // The server generates the protobuf enum names and numbers. Clients do not need to know its naming rules. // The server validates enum vocabulary changes when updating a dataset. // @@ -92,7 +90,7 @@ message FieldAnnotation { // Pair each entry with the corresponding member's number to encode and decode datapoints. List positions // are not enum numbers. The zero member is not a public value; missing fields remain distinct from zero. // Repeated enum fields are deduplicated at ingestion, preserving first-occurrence order in the stored payload. - // Every element must be a declared nonzero member, so the stored list has at most 100 elements. + // Every element must be a declared nonzero member. // Omitted and empty repeated fields are equivalent. Queryable repeated enums support FieldArrayPredicate. repeated EnumValue enum_values = 7 [(buf.validate.field).repeated.max_items = 100]; } diff --git a/apis/workflows/v1/core.proto b/apis/workflows/v1/core.proto index 1fc350c..a66b4be 100644 --- a/apis/workflows/v1/core.proto +++ b/apis/workflows/v1/core.proto @@ -265,8 +265,6 @@ message TaskSubmissionGroup { // containing TaskSubmissions message. repeated uint32 dependencies_on_other_groups = 1; // The input parameters for each task. - // We explicitly don't group the fields into a submessage and then have a single repeated field for that submessage, - // to enable packed encoding of the repeated fields. repeated bytes inputs = 2 [(buf.validate.field).repeated = { min_items: 1 // we don't allow empty submission groups items: { @@ -282,9 +280,9 @@ message TaskSubmissionGroup { // Index of the display name in the display_lookup field of the containing TaskSubmissions message for each task, // specifying a human-readable description of the task. repeated uint64 display_pointers = 5; - // The maximum number of retries for each task. Not a pointer to a lookup table, since we just inline the values. + // The maximum number of retries for each task. repeated int64 max_retries_values = 6; - // Flag indicating whether each task is optional. Not a pointer to a lookup table, since we just inline the values. + // Flag indicating whether each task is optional. repeated bool optional_values = 7; } diff --git a/apis/workflows/v1/resource.proto b/apis/workflows/v1/resource.proto index 4f20720..48d40eb 100644 --- a/apis/workflows/v1/resource.proto +++ b/apis/workflows/v1/resource.proto @@ -21,12 +21,12 @@ message ClusterScope { // Include all current and future clusters in the namespace. bool all_clusters = 1; // Share the value only across these clusters. + // An empty slug selects the default cluster; an empty list does not. // If all selected clusters are deleted, the list stays empty and the value applies nowhere. repeated string cluster_slugs = 2 [ (buf.validate.field).repeated.unique = true, - (buf.validate.field).repeated.items.string.min_len = 1, (buf.validate.field).repeated.items.string.max_len = 100, - (buf.validate.field).repeated.items.string.pattern = "^[A-Za-z0-9-]+$" + (buf.validate.field).repeated.items.string.pattern = "^[A-Za-z0-9-]*$" ]; } @@ -39,22 +39,21 @@ message EnvironmentVariable { // Hide the full value unless the caller asks to reveal it. bool is_secret = 3; ClusterScope scope = 4; - // Get/List return the full value for non-secrets and authorized reveals. Create/Update omit it. + // Get/List return the full value for non-secrets and explicit reveals. Create/Update omit it. // A missing value is hidden. Never log values, even non-secrets. string value = 5 [ features.field_presence = EXPLICIT, debug_redact = true ]; // Get/List return this preview only for hidden secrets. - // Over 20 Unicode code points: first 6 + "***" + last 6. Values of 20 or fewer show "***". - // Readers can see these parts of the secret. Never log the preview or pass it to a runner. + // For display only. Never log the preview or pass it to a runner. // Non-secrets, reveals, and Create/Update responses omit it. string secret_preview = 6 [ features.field_presence = EXPLICIT, debug_redact = true ]; - // A note visible to anyone who can read this entry. Do not put credentials here. - string note = 7; + // A description visible to anyone who can read this entry. Do not put credentials here. + string description = 7; } // RunnerEnvironmentVariable is a resolved value for a runner, with the ID of the entry that supplied it. @@ -70,10 +69,9 @@ message RunnerEnvironmentVariable { // Duplicate all-clusters values or overlapping cluster selections for the same name fail with AlreadyExists. // The request either succeeds in full or makes no changes. message CreateEnvironmentVariableRequest { - // Names are case-sensitive. The backend checks reserved names. - string name = 1 [(buf.validate.field).string.pattern = "^[A-Za-z_][A-Za-z0-9_]*$"]; + // An uppercase environment variable name. + string name = 1 [(buf.validate.field).string.pattern = "^[A-Z_][A-Z0-9_]*$"]; // Must be nonempty. Stored as supplied, without interpolation. Never log it. - // The backend checks value sizes and the total size of the resolved environment. string value = 2 [ debug_redact = true, (buf.validate.field).string.min_len = 1, @@ -89,14 +87,14 @@ message CreateEnvironmentVariableRequest { expression: "this.all_clusters || this.cluster_slugs.size() > 0" } ]; - // Optional note. Readers can see it without revealing the secret. - string note = 5 [(buf.validate.field).string.max_len = 50000]; + // Optional description. Readers can see it without revealing the secret. + string description = 5 [(buf.validate.field).string.max_len = 50000]; } // GetEnvironmentVariableRequest reads one entry in the namespace. message GetEnvironmentVariableRequest { tilebox.v1.ID id = 1 [(buf.validate.field).required = true]; - // Return the full secret if the caller is allowed to reveal it. Do not log or cache the response. + // Include the full secret value. Do not log or cache the response. bool include_secret = 2; } @@ -111,9 +109,9 @@ message ListEnvironmentVariablesRequest { (buf.validate.field).string.max_len = 100, (buf.validate.field).string.pattern = "^[A-Za-z0-9-]*$" ]; - // Return full secrets if the caller is allowed to reveal them. Do not log or cache the response. + // Include full secret values. Do not log or cache the response. bool include_secrets = 3; - // Newest entries first. The default and maximum page size is 100. + // Newest entries first. tilebox.v1.Pagination page = 4 [features.field_presence = EXPLICIT]; } @@ -130,14 +128,14 @@ message UpdateEnvironmentVariableRequest { option (buf.validate.message).cel = { id: "update_environment_variable.fields" message: "At least one update field is required." - expression: "has(this.name) || has(this.value) || has(this.is_secret) || has(this.scope) || has(this.note)" + expression: "has(this.name) || has(this.value) || has(this.is_secret) || has(this.scope) || has(this.description)" }; tilebox.v1.ID id = 1 [(buf.validate.field).required = true]; - // Names are case-sensitive. The backend checks reserved names. + // An uppercase environment variable name. string name = 2 [ features.field_presence = EXPLICIT, - (buf.validate.field).string.pattern = "^[A-Za-z_][A-Za-z0-9_]*$" + (buf.validate.field).string.pattern = "^[A-Z_][A-Z0-9_]*$" ]; // Omit to keep the value. A supplied value must be nonempty. Never log it. string value = 3 [ @@ -155,8 +153,8 @@ message UpdateEnvironmentVariableRequest { message: "Select all clusters or at least one cluster." expression: "this.all_clusters || this.cluster_slugs.size() > 0" }]; - // Omit to keep the note, or send an empty string to clear it. Readers can see it without revealing the secret. - string note = 6 [ + // Omit to keep the description, or send an empty string to clear it. Readers can see it without revealing the secret. + string description = 6 [ features.field_presence = EXPLICIT, (buf.validate.field).string.max_len = 50000 ]; @@ -172,7 +170,7 @@ message DeleteEnvironmentVariableRequest { message DeleteEnvironmentVariableResponse {} // ResourceService manages resources in the caller's namespace, starting with environment variables. -// Creating, updating, and deleting entries requires organization admin rights. Never log values or secret previews. +// Never log values or secret previews. service ResourceService { // Create a new entry. The response omits the value and secret preview. rpc CreateEnvironmentVariable(CreateEnvironmentVariableRequest) returns (EnvironmentVariable); diff --git a/apis/workflows/v1/workflows.proto b/apis/workflows/v1/workflows.proto index 46d5d5f..4e2fdba 100644 --- a/apis/workflows/v1/workflows.proto +++ b/apis/workflows/v1/workflows.proto @@ -64,14 +64,14 @@ message GetClusterRunnerEnvironmentRequest { ]; } -// GetClusterRunnerEnvironmentResponse returns deployments and resolved values from the same snapshot. -// The caller must be allowed to receive the secrets. Never log or cache this response. +// GetClusterRunnerEnvironmentResponse combines cluster deployments with resolved environment values. +// Deployments and values are read separately and may reflect concurrent changes. +// Never log or cache this response. message GetClusterRunnerEnvironmentResponse { - // Includes deployed releases and artifacts, filtered by the same access rules as GetCluster. + // Includes deployed releases and artifacts, as in GetCluster. Cluster cluster = 1; // One entry per name, including full secret values. Cluster-specific values win over all-clusters values. // Values are literal strings, without interpolation. Replace the previous environment, even when this list is empty. - // When values change, runners use a new runtime for new tasks and let running tasks finish on the old one. repeated RunnerEnvironmentVariable environment_variables = 2 [debug_redact = true]; } @@ -360,8 +360,7 @@ message BuildConfig { repeated string include = 1; // File patterns to exclude, relative to the build root. repeated string exclude = 2; - // Whether to apply Git ignore rules. Omitted means true; preserve presence when reconstructing configuration. - // Artifact builders must preserve the applicable ignore files or normalize the rules to remove that dependency. + // Whether to apply Git ignore rules. Omitted means true. bool use_gitignore = 3 [features.field_presence = EXPLICIT]; }