Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions apis/datasets/v1/core.proto
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ edition = "2023";
package datasets.v1;

import "datasets/v1/dataset_type.proto";
import "datasets/v1/presentation.proto";
import "tilebox/v1/id.proto";
import "tilebox/v1/query.proto";

Expand Down Expand Up @@ -86,6 +87,9 @@ message Dataset {
bool type_editable = 13;
// list of collections in the dataset
repeated CollectionInfo collections = 14;
// Optional curated metadata for catalog display and client-side search/filtering, returned in list and get responses.
// Absence means no presentation metadata has been supplied, not that the dataset lacks these capabilities.
DatasetPresentation presentation = 15;
}

// DatasetPermission is a permission a user (as part of an org) can have on a dataset
Expand Down Expand Up @@ -116,4 +120,6 @@ message DatasetGroup {
string name = 4;
// optional icon of the group
string icon = 5;
// Optional short description for the group heading in the catalog. Dataset facets are not inherited from groups.
string summary = 6;
}
7 changes: 5 additions & 2 deletions apis/datasets/v1/dataset_type.proto
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,11 @@ enum FieldRole {

// EnumValue is one allowed value of a custom enum.
message EnumValue {
// The value users ingest, query, and receive, e.g. "L1".
string value = 1 [(buf.validate.field).string.min_len = 1];
// The value users ingest, query, and receive, e.g. "L1", limited to 128 Unicode code points.
string value = 1 [(buf.validate.field).string = {
min_len: 1
max_len: 128
}];
}

// FieldAnnotation contains additional information about a field in a dataset.
Expand Down
5 changes: 5 additions & 0 deletions apis/datasets/v1/datasets.proto
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package datasets.v1;
import "buf/validate/validate.proto";
import "datasets/v1/core.proto";
import "datasets/v1/dataset_type.proto";
import "datasets/v1/presentation.proto";
import "tilebox/v1/id.proto";

option features.field_presence = IMPLICIT;
Expand All @@ -32,6 +33,8 @@ message CreateDatasetRequest {
];
// optional description of the dataset, in markdown format
string description = 5 [(buf.validate.field).string.max_len = 1000000];
// Optional metadata for catalog display and client-side discovery.
DatasetPresentation presentation = 6;
}

// GetDatasetRequest is the request message for the GetDataset RPC method for fetching a single dataset
Expand Down Expand Up @@ -81,6 +84,8 @@ message UpdateDatasetRequest {
features.field_presence = EXPLICIT,
(buf.validate.field).string.max_len = 1000000
];
// Replaces the entire presentation when supplied. Omit to leave unchanged; send an empty message to clear it.
DatasetPresentation presentation = 7 [features.field_presence = EXPLICIT];
}
// DeleteDatasetRequest is used to delete a dataset
message DeleteDatasetRequest {
Expand Down
77 changes: 77 additions & 0 deletions apis/datasets/v1/presentation.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Curated metadata for dataset display and client-side discovery.

edition = "2023";

package datasets.v1;

import "buf/validate/validate.proto";

option features.field_presence = IMPLICIT;

// DatasetPresentation summarizes the whole dataset, without collection or asset scoping.
// Filter values mean the dataset contains these capabilities somewhere, not necessarily together in one product.
// Name, slug, summary, documentation, visibility, and temporal availability remain on Dataset and its collections.
// Missing metadata means unknown/not specified, not confirmed absence.
message DatasetPresentation {
string image_url = 1;
string image_alt = 2;
// e.g. "Optical", "Radar", "Hyperspectral", "Atmosphere".
DatasetPresentationFacet data_type = 3;
// Spectral capabilities, e.g. red, green, blue, red-edge, NIR, SWIR.
// A hyperspectral label may summarize wavelengths and channel counts instead of listing the filter values.
DatasetPresentationFacet bands = 4;
// Delivered products, variables, and quality layers, e.g. NDVI, surface temperature, methane, cloud masks.
DatasetPresentationFacet products = 5;
DatasetPresentationResolution resolution = 6;
// Values: Global, Selected areas, Regional. The label can qualify these, e.g. "Global — Land only".
DatasetPresentationFacet geographic_coverage = 7;
// Exact science-asset formats, e.g. COG, GeoTIFF, JPEG2000, SAFE, HDF5; excludes preview formats.
DatasetPresentationFacet asset_formats = 8;
// Source storage access, independent of Tilebox authentication and dataset visibility.
// Values: No account required, Free account required, Requester pays, Restricted.
// No account required includes freely obtainable tokens, such as Planetary Computer SAS signing.
DatasetPresentationFacet storage_access = 9;
}

// DatasetPresentationFacet combines a compact row summary with independently selectable filter values.
// Values are both filter labels and exact, case-sensitive identities within the facet. Publishers use consistent
// spelling across datasets. Clients deduplicate these strings for dropdowns and slugify them only for URLs.
// Search can include both the row label and values. Bands and products share an All/Any selection
// across both sets. Other facets match any selected value; combine those filters with AND at dataset level.
message DatasetPresentationFacet {
// Optional row text, e.g. "RGB · NIR" or "Visible + near-infrared · 23 or 31 bands".
// When unset or empty, display values joined with " · " in their supplied order.
// Nonempty labels must be single-line text without surrounding whitespace or control characters.
string label = 1 [(buf.validate.field).string.pattern = "^$|^[^\\p{Z}\\p{Cc}](?:[^\\p{Cc}\\p{Zl}\\p{Zp}]*[^\\p{Z}\\p{Cc}])?$"];
// Optional dataset-specific explanation for the row. Plain text, not markup.
string tooltip = 2;
// e.g. ["Red", "Green", "Blue"] or ["Methane (CH₄)"]. Never derive these from the row label.
// Values must be nonempty single-line text without surrounding whitespace or control characters.
repeated string values = 3 [(buf.validate.field).repeated = {
unique: true
items: {
string: {pattern: "^[^\\p{Z}\\p{Cc}](?:[^\\p{Cc}\\p{Zl}\\p{Zp}]*[^\\p{Z}\\p{Cc}])?$"}
}
}];
}

// DatasetPresentationResolution uses numeric filter values rather than named options.
message DatasetPresentationResolution {
// Optional row text, e.g. "10–60 m" or "250 m–1 km". Clients may format the values when omitted.
// Nonempty labels must be single-line text without surrounding whitespace or control characters.
string label = 1 [(buf.validate.field).string.pattern = "^$|^[^\\p{Z}\\p{Cc}](?:[^\\p{Cc}\\p{Zl}\\p{Zp}]*[^\\p{Z}\\p{Cc}])?$"];
// Optional explanation of the resolution basis, e.g. nominal GSD versus radar spatial resolution.
string tooltip = 2;
// Discrete nominal resolutions in metres, not a min/max interval: e.g. [10,20,60] or [250,500,1000].
// Clients derive five bins: (0,1), [1,10), [10,100), [100,1000), [1000,+infinity).
// Match when any value falls in a selected bin. Do not infer values from the display label.
repeated double meters = 3 [(buf.validate.field).repeated = {
unique: true
items: {
double: {
gt: 0
finite: true
}
}
}];
}
Loading