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
186 changes: 186 additions & 0 deletions apis/datasets/stac/v1/asset.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
// This file models STAC 1.1 Asset and Band Objects using Tilebox's compact shared-profile representation. Access and band
// profile tables deduplicate repeated metadata without changing the reconstructed STAC semantics.
//
// https://github.com/radiantearth/stac-spec/blob/v1.1.0/item-spec/item-spec.md#asset-object

edition = "2023";
package datasets.stac.v1;

import "buf/validate/validate.proto";
import "datasets/stac/v1/asset_metadata.proto";
import "datasets/stac/v1/core.proto";
import "datasets/stac/v1/product.proto";
import "datasets/stac/v1/sar.proto";
import "datasets/stac/v1/satellite.proto";

option features.field_presence = IMPLICIT;

// KnownAssetRole contains the STAC 1.1, EO 2.0, and SAR 1.3.2 recommended asset roles. STAC asset roles are open;
// values not listed here are stored in Asset.custom_roles.
enum KnownAssetRole {
KNOWN_ASSET_ROLE_UNSPECIFIED = 0;

// STAC 1.1 recommended asset roles occupy values 1-99.
// https://github.com/radiantearth/stac-spec/blob/v1.1.0/best-practices.md#list-of-asset-roles
KNOWN_ASSET_ROLE_DATA = 1;
KNOWN_ASSET_ROLE_METADATA = 2;
KNOWN_ASSET_ROLE_THUMBNAIL = 3;
KNOWN_ASSET_ROLE_OVERVIEW = 4;
KNOWN_ASSET_ROLE_VISUAL = 5;
KNOWN_ASSET_ROLE_DATE = 6;
KNOWN_ASSET_ROLE_GRAPHIC = 7;
KNOWN_ASSET_ROLE_DATA_MASK = 8;
KNOWN_ASSET_ROLE_SNOW_ICE = 9;
KNOWN_ASSET_ROLE_LAND_WATER = 10;
KNOWN_ASSET_ROLE_WATER_MASK = 11;
KNOWN_ASSET_ROLE_ISO_19115 = 12;

// EO 2.0 best-practice asset roles occupy values 100-199.
// https://github.com/stac-extensions/eo/blob/v2.0.0/README.md#best-practices
KNOWN_ASSET_ROLE_REFLECTANCE = 100;
KNOWN_ASSET_ROLE_TEMPERATURE = 101;
KNOWN_ASSET_ROLE_SATURATION = 102;
KNOWN_ASSET_ROLE_CLOUD = 103;
KNOWN_ASSET_ROLE_CLOUD_SHADOW = 104;

// SAR 1.3.2 best-practice asset roles occupy values 200-299.
// https://github.com/stac-extensions/sar/blob/v1.3.2/README.md#best-practices
KNOWN_ASSET_ROLE_LOCAL_INCIDENCE_ANGLE = 200;
KNOWN_ASSET_ROLE_ELLIPSOID_INCIDENCE_ANGLE = 201;
KNOWN_ASSET_ROLE_NOISE_POWER = 202;
KNOWN_ASSET_ROLE_AMPLITUDE = 203;
KNOWN_ASSET_ROLE_MAGNITUDE = 204;
KNOWN_ASSET_ROLE_SIGMA0 = 205;
KNOWN_ASSET_ROLE_BETA0 = 206;
KNOWN_ASSET_ROLE_GAMMA0 = 207;
KNOWN_ASSET_ROLE_DATE_OFFSET = 208;
KNOWN_ASSET_ROLE_COVMAT = 209;
KNOWN_ASSET_ROLE_PRD = 210;
}

// DataType contains the complete closed STAC 1.1 data_type vocabulary.
enum DataType {
DATA_TYPE_UNSPECIFIED = 0;
DATA_TYPE_INT8 = 1;
DATA_TYPE_INT16 = 2;
DATA_TYPE_INT32 = 3;
DATA_TYPE_INT64 = 4;
DATA_TYPE_UINT8 = 5;
DATA_TYPE_UINT16 = 6;
DATA_TYPE_UINT32 = 7;
DATA_TYPE_UINT64 = 8;
DATA_TYPE_FLOAT16 = 9;
DATA_TYPE_FLOAT32 = 10;
DATA_TYPE_FLOAT64 = 11;
DATA_TYPE_CINT16 = 12;
DATA_TYPE_CINT32 = 13;
DATA_TYPE_CFLOAT32 = 14;
DATA_TYPE_CFLOAT64 = 15;
DATA_TYPE_OTHER = 16;
}

// Statistics contains the statistics fields used by the supported Items.
message Statistics {
double minimum = 1 [features.field_presence = EXPLICIT];
double maximum = 2 [features.field_presence = EXPLICIT];
}

// AssetAccessProfile deduplicates access metadata shared by asset locations in one STAC Item.
message AssetAccessProfile {
// Alternate Assets map key, such as `s3` or `https`, when used for an alternate location.
string alternate_key = 1;
// Default alternate:name for locations using this profile.
string default_alternate_name = 2 [features.field_presence = EXPLICIT];
// Item-specific common URI prefix used to compress hrefs. A location's full href is the byte concatenation of
// base_href and its href suffix; URI reference resolution and path normalization are not applied.
string base_href = 3;
// Keys into the item-level Storage.schemes registry.
repeated string storage_refs = 4;
// Keys into the item-level Authentication.schemes registry.
repeated string auth_refs = 5;
}

// AssetLocation selects an access profile and supplies a relative or absolute href.
message AssetLocation {
// Required index into Assets.access_profiles. Zero is a valid index.
uint32 access_profile_index = 1 [
features.field_presence = EXPLICIT,
(buf.validate.field).required = true
];
// Href suffix for the selected profile. This must be present on primary locations. When absent on an alternate,
// it reuses the primary location's href suffix verbatim before applying the alternate profile's base_href.
// A present empty string represents the selected profile's base_href exactly.
string href = 2 [features.field_presence = EXPLICIT];
// Per-location override for the access profile's default alternate:name.
string alternate_name = 3 [features.field_presence = EXPLICIT];
}

// Band is a reusable STAC 1.1 band profile containing common, EO, Raster, and Classification fields. Fields present
// here override the corresponding inheritable Asset fields; ingestion should omit values lifted to the Asset.
message Band {
string name = 1 [
features.field_presence = EXPLICIT,
(buf.validate.field).string.min_len = 1
];
string description = 2 [features.field_presence = EXPLICIT];
DataType data_type = 3 [(buf.validate.field).enum.defined_only = true];
double nodata = 4 [features.field_presence = EXPLICIT];
string unit = 5 [features.field_presence = EXPLICIT];
EOProperties eo = 6;
RasterProperties raster = 7;
repeated ClassificationClass classes = 8;
// SAR 1.3.2 permits frequency, center-frequency, and bandwidth metadata on Band Objects.
SARProperties sar = 9;
}

// Asset contains the canonical STAC 1.1 Asset Object fields used by the supported Items. Inheritable metadata applies
// to every band unless a Band overrides it. Ingestion should lift values shared by all bands to this level.
message Asset {
option (buf.validate.message).cel = {
id: "asset.primary_href"
message: "the primary asset location must provide an href"
expression: "has(this.primary.href)"
};

// Key from the STAC assets object.
string key = 1 [(buf.validate.field).string.min_len = 1];
AssetLocation primary = 2 [(buf.validate.field).required = true];
repeated AssetLocation alternates = 3;
MediaType media_type = 4;
string title = 5 [features.field_presence = EXPLICIT];
string description = 6 [features.field_presence = EXPLICIT];
// STAC role order is not semantically meaningful. Known roles are stored compactly; all other values remain strings.
repeated KnownAssetRole roles = 7 [(buf.validate.field).repeated.items.enum = {
defined_only: true
not_in: [0]
}];
repeated string custom_roles = 8 [(buf.validate.field).repeated.items.string.min_len = 1];
double gsd = 9 [features.field_presence = EXPLICIT];
// Ordered indices into Assets.band_profiles. References deliberately have no per-use overrides: metadata differences
// require distinct profiles, which keeps reconstruction to direct lookup plus normal STAC Asset-to-Band inheritance.
repeated uint32 band_profile_indices = 10;
DataType data_type = 11 [(buf.validate.field).enum.defined_only = true];
double nodata = 12 [features.field_presence = EXPLICIT];
Statistics statistics = 13;
string unit = 14 [features.field_presence = EXPLICIT];
EOProperties eo = 15;
RasterProperties raster = 16;
Projection projection = 17;
View view = 18;
repeated ClassificationClass classes = 19;
File file = 20;
SARProperties sar = 21;
SatelliteProperties satellite = 22;
ProductProperties product = 23;
}

// Assets contains the shared profile tables and assets of one STAC Item. Asset locations reference access_profiles by
// index, and assets reference band_profiles by ordered indices. Both tables deduplicate repeated metadata; every index
// must reference an existing profile. Band references intentionally cannot override profiles: use a distinct profile
// for every unique Band. Use one access profile with an empty base_href and refs for uncompressed absolute hrefs.
// Empty repeated fields are intentionally canonicalized: protobuf does not distinguish an absent JSON array from [].
message Assets {
repeated AssetAccessProfile access_profiles = 1;
repeated Band band_profiles = 2;
repeated Asset assets = 3;
}
124 changes: 124 additions & 0 deletions apis/datasets/stac/v1/asset_metadata.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// This file models the common STAC extensions used to describe imagery assets, bands, pixel values, spatial grids,
// viewing geometry, and files in Tilebox datasets.
// EO 2.0: https://github.com/stac-extensions/eo/blob/v2.0.0/README.md
// Raster 2.0: https://github.com/stac-extensions/raster/blob/v2.0.0/README.md
// Classification 2.0: https://github.com/stac-extensions/classification/blob/v2.0.0/README.md
// Projection 2.0: https://github.com/stac-extensions/projection/blob/v2.0.0/README.md
// View 1.1: https://github.com/stac-extensions/view/blob/v1.1.0/README.md
// File 2.1: https://github.com/stac-extensions/file/blob/v2.1.0/README.md

edition = "2023";
package datasets.stac.v1;

import "buf/validate/validate.proto";

option features.field_presence = IMPLICIT;

// EOCommonName is the closed EO 2.0 common-name vocabulary.
enum EOCommonName {
EO_COMMON_NAME_UNSPECIFIED = 0;
EO_COMMON_NAME_PAN = 1;
EO_COMMON_NAME_COASTAL = 2;
EO_COMMON_NAME_BLUE = 3;
EO_COMMON_NAME_GREEN = 4;
EO_COMMON_NAME_GREEN05 = 5;
EO_COMMON_NAME_YELLOW = 6;
EO_COMMON_NAME_RED = 7;
EO_COMMON_NAME_REDEDGE = 8;
EO_COMMON_NAME_REDEDGE071 = 9;
EO_COMMON_NAME_REDEDGE075 = 10;
EO_COMMON_NAME_REDEDGE078 = 11;
EO_COMMON_NAME_NIR = 12;
EO_COMMON_NAME_NIR08 = 13;
EO_COMMON_NAME_NIR09 = 14;
EO_COMMON_NAME_CIRRUS = 15;
EO_COMMON_NAME_SWIR16 = 16;
EO_COMMON_NAME_SWIR22 = 17;
EO_COMMON_NAME_LWIR = 18;
EO_COMMON_NAME_LWIR11 = 19;
EO_COMMON_NAME_LWIR12 = 20;
}

// EOProperties contains the EO 2.0 fields that are useful at asset or band level.
// eo:cloud_cover and eo:snow_cover are intentionally omitted: they are typically Item properties and should become
// dedicated top-level Tilebox dataset fields instead of being embedded in Assets.
message EOProperties {
EOCommonName common_name = 1 [(buf.validate.field).enum.defined_only = true];
// Spectral values are expressed in micrometres.
double center_wavelength = 2 [features.field_presence = EXPLICIT];
double full_width_half_max = 3 [features.field_presence = EXPLICIT];
double solar_illumination = 4 [features.field_presence = EXPLICIT];
}

// RasterSampling contains the closed Raster 2.0 raster:sampling vocabulary.
enum RasterSampling {
RASTER_SAMPLING_UNSPECIFIED = 0;
RASTER_SAMPLING_AREA = 1;
RASTER_SAMPLING_POINT = 2;
}

// RasterProperties contains the Raster 2.0 fields used by the supported Items.
message RasterProperties {
RasterSampling sampling = 1 [(buf.validate.field).enum.defined_only = true];
double scale = 2 [features.field_presence = EXPLICIT];
double offset = 3 [features.field_presence = EXPLICIT];
// Spatial resolution is expressed in metres.
double spatial_resolution = 4 [features.field_presence = EXPLICIT];
}

// ClassificationClass contains all Classification 2.0 class fields. Bit-field definitions are intentionally deferred.
message ClassificationClass {
int64 value = 1 [
features.field_presence = EXPLICIT,
(buf.validate.field).required = true
];
string description = 2 [features.field_presence = EXPLICIT];
string name = 3 [
features.field_presence = EXPLICIT,
(buf.validate.field).required = true,
(buf.validate.field).string.pattern = "^[0-9A-Za-z-_]+$"
];
string title = 4 [features.field_presence = EXPLICIT];
string color_hint = 5 [
features.field_presence = EXPLICIT,
(buf.validate.field).string.pattern = "^[0-9A-Fa-f]{6}$"
];
bool nodata = 6 [features.field_presence = EXPLICIT];
double percentage = 7 [
features.field_presence = EXPLICIT,
(buf.validate.field).double = {
gte: 0
lte: 100
}
];
uint64 count = 8 [features.field_presence = EXPLICIT];
}

// Projection contains the Projection 2.0 fields used by the supported Items.
message Projection {
// Explicit presence distinguishes a missing code from a value. A STAC JSON null is treated as missing.
string code = 1 [
features.field_presence = EXPLICIT,
(buf.validate.field).string.min_len = 1
];
// Four values describe a 2D bbox and six values describe a 3D bbox.
repeated double bbox = 2;
// Exactly two integers in Y, X order.
repeated int64 shape = 3;
// Six values describe a 2D affine transform and nine values describe a 3D transform.
repeated double transform = 4;
}

// View contains the View 1.1 fields used by the supported Items.
message View {
double incidence_angle = 1 [features.field_presence = EXPLICIT];
double azimuth = 2 [features.field_presence = EXPLICIT];
}

// File contains the File 2.1 fields used by the supported Items.
message File {
// Decoded binary multihash. STAC JSON represents this as lowercase hexadecimal.
bytes checksum = 1 [features.field_presence = EXPLICIT];
uint64 size = 2 [features.field_presence = EXPLICIT];
string local_path = 3 [features.field_presence = EXPLICIT];
}
Loading
Loading