From a8f85d15ad15cca76b63ee02c023916e5a1faab1 Mon Sep 17 00:00:00 2001 From: Corentin Musard Date: Mon, 21 Jul 2025 16:07:56 +0200 Subject: [PATCH] Add protovalidate rules for datasets --- apis/datasets/v1/collections.proto | 34 +++++--- apis/datasets/v1/core.proto | 39 +++++---- apis/datasets/v1/data_access.proto | 104 ++++++++++++++++-------- apis/datasets/v1/data_ingestion.proto | 40 ++++----- apis/datasets/v1/dataset_type.proto | 34 +++++--- apis/datasets/v1/datasets.proto | 32 +++++--- apis/datasets/v1/well_known_types.proto | 83 ++++++++++++------- apis/tilebox/v1/query.proto | 6 +- 8 files changed, 237 insertions(+), 135 deletions(-) diff --git a/apis/datasets/v1/collections.proto b/apis/datasets/v1/collections.proto index aa303e3..50a252a 100644 --- a/apis/datasets/v1/collections.proto +++ b/apis/datasets/v1/collections.proto @@ -4,6 +4,7 @@ edition = "2023"; package datasets.v1; +import "buf/validate/validate.proto"; import "datasets/v1/core.proto"; import "tilebox/v1/id.proto"; @@ -11,22 +12,30 @@ option features.field_presence = IMPLICIT; // CreateCollectionRequest is used to create a new collection. message CreateCollectionRequest { - tilebox.v1.ID dataset_id = 1; // The dataset id where the collection should be created. - string name = 2; // The name of the collection to create. + // The dataset id where the collection should be created. + tilebox.v1.ID dataset_id = 1 [(buf.validate.field).required = true]; + // The name of the collection to create. + string name = 2 [(buf.validate.field).string.min_len = 1]; } // GetCollectionByNameRequest contains the request parameters for retrieving a single collection by its name. message GetCollectionByNameRequest { - string collection_name = 1; // The name of the collection to retrieve. - bool with_availability = 2; // If true, the response will include the availability interval. - bool with_count = 3; // If true, the response will include the number of entries. - tilebox.v1.ID dataset_id = 4; // The dataset id. + // The name of the collection to retrieve. + string collection_name = 1 [(buf.validate.field).string.min_len = 1]; + // If true, the response will include the availability interval. + bool with_availability = 2; + // If true, the response will include the number of entries. + bool with_count = 3; + // The dataset id. + tilebox.v1.ID dataset_id = 4 [(buf.validate.field).required = true]; } // DeleteCollectionRequest contains the request parameters for deleting a single collection. message DeleteCollectionRequest { - tilebox.v1.ID collection_id = 1; // The id of the collection to delete. - tilebox.v1.ID dataset_id = 2; // The dataset id. + // The id of the collection to delete. + tilebox.v1.ID collection_id = 1 [(buf.validate.field).required = true]; + // The dataset id. + tilebox.v1.ID dataset_id = 2 [(buf.validate.field).required = true]; } // DeleteCollectionResponse is the response to DeleteCollectionRequest. @@ -35,9 +44,12 @@ message DeleteCollectionResponse {} // ListCollectionsRequest contains the request parameters // for retrieving a list of all available collections for a given dataset. message ListCollectionsRequest { - tilebox.v1.ID dataset_id = 1; // The dataset id. - bool with_availability = 2; // If true, the response will include the availability interval. - bool with_count = 3; // If true, the response will include the number of entries. + // The dataset id. + tilebox.v1.ID dataset_id = 1 [(buf.validate.field).required = true]; + // If true, the response will include the availability interval. + bool with_availability = 2; + // If true, the response will include the number of entries. + bool with_count = 3; } // CollectionService is the service definition for the Tilebox datasets service, which provides access to datasets diff --git a/apis/datasets/v1/core.proto b/apis/datasets/v1/core.proto index 90baea7..ba17cc7 100644 --- a/apis/datasets/v1/core.proto +++ b/apis/datasets/v1/core.proto @@ -56,33 +56,36 @@ message RepeatedAny { // DatapointMetadata contains the metadata for a single data point. // legacy, only relevant for old endpoints message DatapointMetadata { - google.protobuf.Timestamp event_time = 1; // The time the message was received by the on-board computer. - google.protobuf.Timestamp ingestion_time = 2; // The time the message was ingested by Tilebox. - string id = 3 [features.field_presence = EXPLICIT]; // The external id of the datapoint. -} - -// Datapoints is a list of datapoints in a Tilebox dataset, with all data points sharing the same type. -message Datapoints { - repeated DatapointMetadata meta = 1; // A metadata for a datapoint. - RepeatedAny data = 2; // The datapoints. + // The time the message was received by the on-board computer. + google.protobuf.Timestamp event_time = 1; + // The time the message was ingested by Tilebox. + google.protobuf.Timestamp ingestion_time = 2; + // The external id of the datapoint. + string id = 3 [features.field_presence = EXPLICIT]; } // DatapointPage is a single page of data points of a Tilebox dataset, such as it is returned by a ForInterval query message DatapointPage { - repeated DatapointMetadata meta = 1; // A metadata for a datapoint. - RepeatedAny data = 2; // The datapoints. - LegacyPagination next_page = 3 [features.field_presence = EXPLICIT]; // The pagination parameters for the next page. + // A metadata for a datapoint. + repeated DatapointMetadata meta = 1; + // The datapoints. + RepeatedAny data = 2; + // The pagination parameters for the next page. + LegacyPagination next_page = 3 [features.field_presence = EXPLICIT]; } // Datapoint is a single datapoint in a Tilebox Dataset message Datapoint { - DatapointMetadata meta = 1; // A metadata for a datapoint. - Any data = 2; // The data. + // A metadata for a datapoint. + DatapointMetadata meta = 1; + // The data. + Any data = 2; } // Collection contains basic information about a dataset collection message Collection { - string legacy_id = 1; // Here for backwards compatibility, to be removed in the future. + // Here for backwards compatibility, to be removed in the future. + string legacy_id = 1; string name = 2; tilebox.v1.ID id = 3; } @@ -90,8 +93,10 @@ message Collection { // CollectionInfo contains information about the data available in a dataset collection message CollectionInfo { Collection collection = 1; - tilebox.v1.TimeInterval availability = 2 [features.field_presence = EXPLICIT]; // The time interval for which data is available. - uint64 count = 3 [features.field_presence = EXPLICIT]; // Number of entries in the dataset. + // The time interval for which data is available. + tilebox.v1.TimeInterval availability = 2 [features.field_presence = EXPLICIT]; + // Number of entries in the dataset. + uint64 count = 3 [features.field_presence = EXPLICIT]; } // CollectionInfos contains a list of CollectionInfo messages. diff --git a/apis/datasets/v1/data_access.proto b/apis/datasets/v1/data_access.proto index 6c7d8c2..20bab03 100644 --- a/apis/datasets/v1/data_access.proto +++ b/apis/datasets/v1/data_access.proto @@ -4,6 +4,7 @@ edition = "2023"; package datasets.v1; +import "buf/validate/validate.proto"; import "datasets/v1/core.proto"; import "datasets/v1/well_known_types.proto"; import "tilebox/v1/id.proto"; @@ -14,14 +15,19 @@ option features.field_presence = IMPLICIT; // Legacy message, to be removed in the future. // GetDatasetForIntervalRequest contains the request parameters for retrieving data for a time interval. message GetDatasetForIntervalRequest { - string collection_id = 1; // The collection id. + // The collection id. + string collection_id = 1; // Either time interval or datapoint interval must be set, but not both. - tilebox.v1.TimeInterval time_interval = 2; // The time interval for which data is requested. - tilebox.v1.IDInterval datapoint_interval = 6; // The datapoint interval for which data is requested. - - LegacyPagination page = 3 [features.field_presence = EXPLICIT]; // The pagination parameters for this request. - bool skip_data = 4; // If true, the datapoint data is not returned. + // The time interval for which data is requested. + tilebox.v1.TimeInterval time_interval = 2; + // The datapoint interval for which data is requested. + tilebox.v1.IDInterval datapoint_interval = 6; + + // The pagination parameters for this request. + LegacyPagination page = 3 [features.field_presence = EXPLICIT]; + // If true, the datapoint data is not returned. + bool skip_data = 4; // If true, the datapoint metadata is not returned. // If both skip_data and skip_meta are true, // the response will only consist of a list of datapoint ids without any additional data or metadata. @@ -31,64 +37,96 @@ message GetDatasetForIntervalRequest { // Legacy message, to be removed in the future. // GetDatapointByIdRequest contains the request parameters for retrieving a single data point in a collection by its id. message GetDatapointByIdRequest { - string collection_id = 1; // The collection id. - string id = 2; // The id of the requested data point. - bool skip_data = 3; // If true, only the datapoint metadata is returned. + // The collection id. + string collection_id = 1; + // The id of the requested data point. + string id = 2; + // If true, only the datapoint metadata is returned. + bool skip_data = 3; } // QueryByIDRequest contains the request parameters for retrieving a single data point by its id. message QueryByIDRequest { - repeated tilebox.v1.ID collection_ids = 1; // collection ids to query. - tilebox.v1.ID id = 2; // The id of the requested data point. - bool skip_data = 3; // If true, only the datapoint metadata is returned. + // collection ids to query. + repeated tilebox.v1.ID collection_ids = 1 [(buf.validate.field).repeated = { + min_items: 1 + max_items: 100 + }]; + // The id of the requested data point. + tilebox.v1.ID id = 2 [(buf.validate.field).required = true]; + // If true, only the datapoint metadata is returned. + bool skip_data = 3; } // QueryFilters contains the filters to apply to a query. message QueryFilters { - // Either a time interval or datapoint interval must be set, but not both. - oneof temporal_extent { - tilebox.v1.TimeInterval time_interval = 1; - tilebox.v1.IDInterval datapoint_interval = 2; - } + option (buf.validate.message).oneof = { + fields: [ + "time_interval", + "datapoint_interval" + ] + required: true + }; + + tilebox.v1.TimeInterval time_interval = 1; + tilebox.v1.IDInterval datapoint_interval = 2; SpatialFilter spatial_extent = 3; } // SpatialFilterMode specifies how geometries are compared to a given spatial filter. enum SpatialFilterMode { - SPATIAL_FILTER_MODE_UNSPECIFIED = 0; // Unspecified spatial filter mode, will default to intersects. - SPATIAL_FILTER_MODE_INTERSECTS = 1; // Any geometry that intersects the filter geometry is included. - SPATIAL_FILTER_MODE_CONTAINS = 2; // Only geometries fully contained within the filter geometry are included. + // Unspecified spatial filter mode, will default to intersects. + SPATIAL_FILTER_MODE_UNSPECIFIED = 0; + // Any geometry that intersects the filter geometry is included. + SPATIAL_FILTER_MODE_INTERSECTS = 1; + // Only geometries fully contained within the filter geometry are included. + SPATIAL_FILTER_MODE_CONTAINS = 2; } // SpatialCoordinateSystem specifies the coordinate system in which to perform geometry calculations such as // intersections. enum SpatialCoordinateSystem { - SPATIAL_COORDINATE_SYSTEM_UNSPECIFIED = 0; // Unspecified coordinate system, will default to cartesian. - SPATIAL_COORDINATE_SYSTEM_CARTESIAN = 1; // Cartesian (lat/lon) coordinate system - SPATIAL_COORDINATE_SYSTEM_SPHERICAL = 2; // Spherical (x/y/z) coordinate system + // Unspecified coordinate system, will default to cartesian. + SPATIAL_COORDINATE_SYSTEM_UNSPECIFIED = 0; + // Cartesian (lat/lon) coordinate system + SPATIAL_COORDINATE_SYSTEM_CARTESIAN = 1; + // Spherical (x/y/z) coordinate system + SPATIAL_COORDINATE_SYSTEM_SPHERICAL = 2; } // SpatialFilter defines a spatial filter operation as part of a query. message SpatialFilter { - Geometry geometry = 1; // The geometry to filter by. - SpatialFilterMode mode = 2; // Whether to filter by intersection or containment. - SpatialCoordinateSystem coordinate_system = 3; // Coordinate system in which to perform geometry calculations. + // The geometry to filter by. + Geometry geometry = 1 [(buf.validate.field).required = true]; + // Whether to filter by intersection or containment. + SpatialFilterMode mode = 2 [(buf.validate.field).enum.defined_only = true]; + // Coordinate system in which to perform geometry calculations. + SpatialCoordinateSystem coordinate_system = 3 [(buf.validate.field).enum.defined_only = true]; } // QueryRequest contains the request parameters for retrieving data from a Tilebox dataset. message QueryRequest { - repeated tilebox.v1.ID collection_ids = 1; // collection ids to query. - QueryFilters filters = 2; // Filters to apply to the query. - - tilebox.v1.Pagination page = 3 [features.field_presence = EXPLICIT]; // The pagination parameters for this request. - bool skip_data = 4; // If true, only datapoint metadata, such as id, time and ingestion_time are returned. + // collection ids to query. + repeated tilebox.v1.ID collection_ids = 1 [(buf.validate.field).repeated = { + min_items: 1 + max_items: 100 + }]; + // Filters to apply to the query. + QueryFilters filters = 2; + + // The pagination parameters for this request. + tilebox.v1.Pagination page = 3 [features.field_presence = EXPLICIT]; + // If true, only datapoint metadata, such as id, time and ingestion_time are returned. + bool skip_data = 4; } // QueryResultPage is a single page of data points of a Tilebox dataset message QueryResultPage { - RepeatedAny data = 1; // The datapoints. - tilebox.v1.Pagination next_page = 2 [features.field_presence = EXPLICIT]; // The pagination parameters for the next page. + // The datapoints. + RepeatedAny data = 1; + // The pagination parameters for the next page. + tilebox.v1.Pagination next_page = 2 [features.field_presence = EXPLICIT]; } // DataAccessService provides data access and querying capabilities for Tilebox datasets. diff --git a/apis/datasets/v1/data_ingestion.proto b/apis/datasets/v1/data_ingestion.proto index 494b445..aec78e6 100644 --- a/apis/datasets/v1/data_ingestion.proto +++ b/apis/datasets/v1/data_ingestion.proto @@ -4,32 +4,22 @@ edition = "2023"; package datasets.v1; -import "datasets/v1/core.proto"; +import "buf/validate/validate.proto"; import "tilebox/v1/id.proto"; option features.field_presence = IMPLICIT; -// Legacy ingest request -// IngestDatapointsRequest is used to ingest one or multiple datapoints into a collection. -message IngestDatapointsRequest { - tilebox.v1.ID collection_id = 1; // The collection to insert the datapoints into. - - Datapoints datapoints = 2; - - // Whether to allow existing datapoints as part of the request. If true, datapoints that already exist will be - // ignored, and the number of such existing datapoints will be returned in the response. If false, any datapoints - // that already exist will result in an error. Setting this to true is useful for achieving idempotency (e.g. - // allowing re-ingestion of datapoints that have already been ingested in the past). - bool allow_existing = 3; -} - // IngestRequest is used to ingest one or multiple datapoints into a collection. message IngestRequest { - tilebox.v1.ID collection_id = 1; // The collection to insert the datapoints into. + // The collection to insert the datapoints into. + tilebox.v1.ID collection_id = 1 [(buf.validate.field).required = true]; // The datapoints to insert. The values here are encoded protobuf messages. The type of the message is determined // by the type of the dataset that the specified collection belongs to. - repeated bytes values = 2; + repeated bytes values = 2 [ + (buf.validate.field).repeated.max_items = 8192, + (buf.validate.field).repeated.items.bytes.min_len = 1 + ]; // Whether to allow existing datapoints as part of the request. If true, datapoints that already exist will be // ignored, and the number of such existing datapoints will be returned in the response. If false, any datapoints @@ -41,20 +31,24 @@ message IngestRequest { // IngestResponse is the response to a IngestRequest, indicating the number of datapoints that were // ingested as well as the generated ids for those datapoints. message IngestResponse { - int64 num_created = 1; // The number of datapoints that were created. - int64 num_existing = 2; // The number of datapoints that were ignored because they already existed. - repeated tilebox.v1.ID datapoint_ids = 3; // The ids of the datapoints in the same order as the datapoints in the request. + // The number of datapoints that were created. + int64 num_created = 1; + // The number of datapoints that were ignored because they already existed. + int64 num_existing = 2; + // The ids of the datapoints in the same order as the datapoints in the request. + repeated tilebox.v1.ID datapoint_ids = 3; } // DeleteRequest is used to delete multiple datapoints from a collection. message DeleteRequest { - tilebox.v1.ID collection_id = 1; - repeated tilebox.v1.ID datapoint_ids = 2; + tilebox.v1.ID collection_id = 1 [(buf.validate.field).required = true]; + repeated tilebox.v1.ID datapoint_ids = 2 [(buf.validate.field).repeated.max_items = 8192]; } // DeleteResponse is used to indicate that multiple datapoints were deleted. message DeleteResponse { - int64 num_deleted = 1; // The number of datapoints that were deleted. + // The number of datapoints that were deleted. + int64 num_deleted = 1; } // DataIngestionService provides data ingestion and deletion capabilities for Tilebox datasets. diff --git a/apis/datasets/v1/dataset_type.proto b/apis/datasets/v1/dataset_type.proto index 13cca79..e4677f2 100644 --- a/apis/datasets/v1/dataset_type.proto +++ b/apis/datasets/v1/dataset_type.proto @@ -4,6 +4,7 @@ edition = "2023"; package datasets.v1; +import "buf/validate/validate.proto"; import "datasets/v1/well_known_types.proto"; import "google/protobuf/descriptor.proto"; import "google/protobuf/timestamp.proto"; @@ -16,14 +17,14 @@ message Field { // The descriptor contains the name of the field, the type, optional labels (e.g. repeated) and other information. // If the type is TYPE_MESSAGE, then the type_name must be a fully qualified name to a well known type, e.g. // `datasets.v1.Vec3` or `google.protobuf.Timestamp`. - google.protobuf.FieldDescriptorProto descriptor = 1; + google.protobuf.FieldDescriptorProto descriptor = 1 [(buf.validate.field).required = true]; // An optional description and example value for the field. FieldAnnotation annotation = 2; // A flag indicating whether the field should be queryable. This means we will build an index for the field, and // allow users to query for certain values server-side. - bool queryable = 3; + bool queryable = 3 [(buf.validate.field).bool.const = false]; } // DatasetKind is an enum describing the kind of dataset. A dataset kind specifies a set of default fields, that @@ -49,7 +50,10 @@ message FieldAnnotation { message DatasetType { // kind denotes the kind of dataset this type describes. We do not rely on the default fields to be set in our // array of fields - since that way users could circumvent those by manually sending requests not from our Console. - DatasetKind kind = 1; + DatasetKind kind = 1 [(buf.validate.field).enum = { + defined_only: true + not_in: [0] + }]; // A list of fields that this dataset consists of. repeated Field fields = 2; @@ -58,7 +62,8 @@ message DatasetType { // AnnotatedType describes a message type message AnnotatedType { google.protobuf.FileDescriptorSet descriptor_set = 1; - string type_url = 2; // the url of the type, one of the types defined in the descriptor + // the url of the type, one of the types defined in the descriptor + string type_url = 2; reserved 3; repeated FieldAnnotation field_annotations = 4; DatasetKind kind = 5; @@ -67,16 +72,23 @@ message AnnotatedType { // TemporalDatapoint is a single datapoint in a temporal dataset. The message is a superset of all // message types that are Temporal Datasets. message TemporalDatapoint { - google.protobuf.Timestamp time = 1; // The timestamp associated with ach data point. - tilebox.v1.ID id = 2; // A universally unique identifier (UUID) that uniquely identifies each data point. - google.protobuf.Timestamp ingestion_time = 3; // The time the data point was ingested into the Tilebox API. + // The timestamp associated with each data point. + google.protobuf.Timestamp time = 1; + // A universally unique identifier (UUID) that uniquely identifies each data point. + tilebox.v1.ID id = 2; + // The time the data point was ingested into the Tilebox API. + google.protobuf.Timestamp ingestion_time = 3; } // SpatioTemporalDatapoint is a single datapoint in a spatiotemporal dataset. The message is a superset of all // message types that are spatiotemporal Datasets. message SpatioTemporalDatapoint { - google.protobuf.Timestamp time = 1; // The timestamp associated with each data point. - tilebox.v1.ID id = 2; // A universally unique identifier (UUID) that uniquely identifies each data point. - google.protobuf.Timestamp ingestion_time = 3; // The time the data point was ingested into the Tilebox API. - Geometry geometry = 4; // The geometry associated with each data point. + // The timestamp associated with each data point. + google.protobuf.Timestamp time = 1; + // A universally unique identifier (UUID) that uniquely identifies each data point. + tilebox.v1.ID id = 2; + // The time the data point was ingested into the Tilebox API. + google.protobuf.Timestamp ingestion_time = 3; + // The geometry associated with each data point. + Geometry geometry = 4; } diff --git a/apis/datasets/v1/datasets.proto b/apis/datasets/v1/datasets.proto index 428b324..9d3e7e9 100644 --- a/apis/datasets/v1/datasets.proto +++ b/apis/datasets/v1/datasets.proto @@ -4,6 +4,7 @@ edition = "2023"; package datasets.v1; +import "buf/validate/validate.proto"; import "datasets/v1/core.proto"; import "datasets/v1/dataset_type.proto"; import "tilebox/v1/id.proto"; @@ -13,19 +14,28 @@ option features.field_presence = IMPLICIT; // CreateDatasetRequest is used to create a new dataset. message CreateDatasetRequest { // name of the dataset to create. - string name = 1; + string name = 1 [(buf.validate.field).string.min_len = 1]; // message type of the dataset to create. - DatasetType type = 2; + DatasetType type = 2 [(buf.validate.field).required = true]; // short text summary of the dataset to create. - string summary = 3; + string summary = 3 [(buf.validate.field).string.min_len = 1]; // normalized snake case name of the dataset to create. - string code_name = 4; + string code_name = 4 [(buf.validate.field).string.min_len = 1]; } // GetDatasetRequest is the request message for the GetDataset RPC method for fetching a single dataset message GetDatasetRequest { + option (buf.validate.message).oneof = { + fields: [ + "slug", + "id" + ] + required: true + }; + // slug of the dataset to be returned, e.g. "open_data.copernicus.sentinel1_sar" - string slug = 1; + // it must contain at least one group and one dataset code name separated by a "." + string slug = 1 [(buf.validate.field).string.pattern = "^[a-z0-9_]+(\\.[a-z0-9_]+)+$"]; // or alternatively a dataset id tilebox.v1.ID id = 2; } @@ -33,13 +43,13 @@ message GetDatasetRequest { // UpdateDatasetRequest is used to update a dataset. message UpdateDatasetRequest { // id of the dataset to update. - tilebox.v1.ID id = 1; + tilebox.v1.ID id = 1 [(buf.validate.field).required = true]; // updated name of the dataset. - string name = 2; + string name = 2 [(buf.validate.field).string.min_len = 1]; // updated type of the dataset. - DatasetType type = 3; + DatasetType type = 3 [(buf.validate.field).required = true]; // updated summary of the dataset. - string summary = 4; + string summary = 4 [(buf.validate.field).string.min_len = 1]; } // ClientInfo contains information about the client requesting datasets, useful for us to gather usage data @@ -63,7 +73,7 @@ message Package { // UpdateDatasetDescriptionRequest is used to update a dataset description message UpdateDatasetDescriptionRequest { // dataset id - tilebox.v1.ID id = 1; + tilebox.v1.ID id = 1 [(buf.validate.field).required = true]; // description of the dataset, in markdown format string description = 2; } @@ -71,7 +81,7 @@ message UpdateDatasetDescriptionRequest { // DeleteDatasetRequest is used to delete a dataset message DeleteDatasetRequest { // id of the dataset to delete. - tilebox.v1.ID id = 1; + tilebox.v1.ID id = 1 [(buf.validate.field).required = true]; } // DeleteDatasetResponse is the response to DeleteDatasetRequest diff --git a/apis/datasets/v1/well_known_types.proto b/apis/datasets/v1/well_known_types.proto index 699a809..997f28a 100644 --- a/apis/datasets/v1/well_known_types.proto +++ b/apis/datasets/v1/well_known_types.proto @@ -63,15 +63,19 @@ enum ObservationDirection { // The open data provider. enum OpendataProvider { OPENDATA_PROVIDER_UNSPECIFIED = 0; - OPENDATA_PROVIDER_ASF = 1; // Alaska Satellite Facility - OPENDATA_PROVIDER_COPERNICUS_DATASPACE = 2; // Copernicus Dataspace - OPENDATA_PROVIDER_UMBRA = 3; // Umbra Space + // Alaska Satellite Facility + OPENDATA_PROVIDER_ASF = 1; + // Copernicus Dataspace + OPENDATA_PROVIDER_COPERNICUS_DATASPACE = 2; + // Umbra Space + OPENDATA_PROVIDER_UMBRA = 3; } // https://www.earthdata.nasa.gov/engage/open-data-services-and-software/data-information-policy/data-levels enum ProcessingLevel { PROCESSING_LEVEL_UNSPECIFIED = 0; - PROCESSING_LEVEL_L0 = 12; // Raw data + // Raw data + PROCESSING_LEVEL_L0 = 12; PROCESSING_LEVEL_L1 = 10; PROCESSING_LEVEL_L1A = 1; PROCESSING_LEVEL_L1B = 2; @@ -91,42 +95,65 @@ enum ProcessingLevel { // Polarization of the radar signal. enum Polarization { - // Horizontal transmit, Horizontal receive POLARIZATION_UNSPECIFIED = 0; + // Horizontal transmit, Horizontal receive POLARIZATION_HH = 1; - POLARIZATION_HV = 2; // Horizontal transmit, Vertical receive - POLARIZATION_VH = 3; // Vertical transmit, Horizontal receive - POLARIZATION_VV = 4; // Vertical transmit, Vertical receive - POLARIZATION_DUAL_HH = 5; // HH+HH - POLARIZATION_DUAL_HV = 6; // HV+HV - POLARIZATION_DUAL_VH = 7; // VH+VH - POLARIZATION_DUAL_VV = 8; // VV+VV - POLARIZATION_HH_HV = 9; // HH+HV - POLARIZATION_VV_VH = 10; // VV+VH + // Horizontal transmit, Vertical receive + POLARIZATION_HV = 2; + // Vertical transmit, Horizontal receive + POLARIZATION_VH = 3; + // Vertical transmit, Vertical receive + POLARIZATION_VV = 4; + // HH+HH + POLARIZATION_DUAL_HH = 5; + // HV+HV + POLARIZATION_DUAL_HV = 6; + // VH+VH + POLARIZATION_DUAL_VH = 7; + // VV+VV + POLARIZATION_DUAL_VV = 8; + // HH+HV + POLARIZATION_HH_HV = 9; + // VV+VH + POLARIZATION_VV_VH = 10; } // Sentinel-1 SAR (beam mode): // https://sentinels.copernicus.eu/web/sentinel/technical-guides/sentinel-1-sar/sar-instrument/acquisition-modes enum AcquisitionMode { - ACQUISITION_MODE_UNSPECIFIED = 0; // In case it is not set for a dataset + // In case it is not set for a dataset + ACQUISITION_MODE_UNSPECIFIED = 0; // used by Sentinel-1 SAR: - ACQUISITION_MODE_SM = 1; // Strip Map - ACQUISITION_MODE_EW = 2; // Extra Wide Swath - ACQUISITION_MODE_IW = 3; // Interferometric Wide Swath - ACQUISITION_MODE_WV = 4; // Wave + // Strip Map + ACQUISITION_MODE_SM = 1; + // Extra Wide Swath + ACQUISITION_MODE_EW = 2; + // Interferometric Wide Swath + ACQUISITION_MODE_IW = 3; + // Wave + ACQUISITION_MODE_WV = 4; // used by Umbra SAR: - ACQUISITION_MODE_SPOTLIGHT = 10; // Spotlight + // Spotlight + ACQUISITION_MODE_SPOTLIGHT = 10; // used by Sentinel 2 MSI: - ACQUISITION_MODE_NOBS = 20; // Nominal Observation - ACQUISITION_MODE_EOBS = 21; // Extended Observation - ACQUISITION_MODE_DASC = 22; // Dark Signal Calibration - ACQUISITION_MODE_ABSR = 23; // Absolute Radiometry Calibration - ACQUISITION_MODE_VIC = 24; // Vicarious Calibration - ACQUISITION_MODE_RAW = 25; // Raw Measurement - ACQUISITION_MODE_TST = 26; // Test Mode + // Nominal Observation + ACQUISITION_MODE_NOBS = 20; + // Extended Observation + ACQUISITION_MODE_EOBS = 21; + // Dark Signal Calibration + ACQUISITION_MODE_DASC = 22; + // Absolute Radiometry Calibration + ACQUISITION_MODE_ABSR = 23; + // Vicarious Calibration + ACQUISITION_MODE_VIC = 24; + // Raw Measurement + ACQUISITION_MODE_RAW = 25; + // Test Mode + ACQUISITION_MODE_TST = 26; } // Geometry is of a particular type, e.g. POINT, POLYGON, MULTIPOLYGON, encoded in a binary format message Geometry { - bytes wkb = 1; // well-known binary representation of a geometry + // well-known binary representation of a geometry + bytes wkb = 1; } diff --git a/apis/tilebox/v1/query.proto b/apis/tilebox/v1/query.proto index 41e33fc..0746f58 100644 --- a/apis/tilebox/v1/query.proto +++ b/apis/tilebox/v1/query.proto @@ -2,6 +2,7 @@ edition = "2023"; package tilebox.v1; +import "buf/validate/validate.proto"; import "google/protobuf/timestamp.proto"; import "tilebox/v1/id.proto"; @@ -42,7 +43,10 @@ message IDInterval { // Pagination information for paginated queries message Pagination { // The maximum number of entries to return. - int64 limit = 1 [features.field_presence = EXPLICIT]; + int64 limit = 1 [ + features.field_presence = EXPLICIT, + (buf.validate.field).int64.gte = 1 + ]; // Return entries starting after this entry. // This is the id of the last entry returned in the previous page as the next parameter in each paginated query. tilebox.v1.ID starting_after = 2 [features.field_presence = EXPLICIT];